Created
October 25, 2018 20:35
-
-
Save AnthonyFJGarner/7e80315099c56cee87e1e374efc42070 to your computer and use it in GitHub Desktop.
VIX Strangle
This file contains hidden or 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
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 23, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:13:44.393089Z", | |
"start_time": "2018-10-06T17:13:44.379164Z" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"#Imports\n", | |
"%matplotlib notebook\n", | |
"import latex\n", | |
"import pandas as pd\n", | |
"import numpy as np\n", | |
"from typing import Dict, List\n", | |
"from collections import OrderedDict\n", | |
"import datetime as datetime\n", | |
"from pandas.tseries.offsets import *\n", | |
"from IPython.core.debugger import set_trace\n", | |
"import matplotlib\n", | |
"matplotlib.style.use('seaborn-darkgrid')\n", | |
"#import pixiedust\n", | |
"#ctrl-shift-p for the command palette\n", | |
"pd.set_option(\"max_colwidth\", 100)\n", | |
"pd.set_option(\"display.max_rows\", 100000)\n", | |
"pd.set_option(\"display.max_columns\", 1000)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 24, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:13:44.416102Z", | |
"start_time": "2018-10-06T17:13:44.395083Z" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>Date</th>\n", | |
" <th>Adj Close</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>2002-07-30</td>\n", | |
" <td>44.934986</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>2002-07-31</td>\n", | |
" <td>45.491722</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2</th>\n", | |
" <td>2002-08-01</td>\n", | |
" <td>45.750809</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>3</th>\n", | |
" <td>2002-08-02</td>\n", | |
" <td>46.219330</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>4</th>\n", | |
" <td>2002-08-05</td>\n", | |
" <td>46.423298</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Date Adj Close\n", | |
"0 2002-07-30 44.934986\n", | |
"1 2002-07-31 45.491722\n", | |
"2 2002-08-01 45.750809\n", | |
"3 2002-08-02 46.219330\n", | |
"4 2002-08-05 46.423298" | |
] | |
}, | |
"execution_count": 24, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"#bonds_file='../data/Options/IEF.csv'\n", | |
"bonds_file='../data/Options/TLT.csv'\n", | |
"#bonds_file='../data/Options/SHY.csv'\n", | |
"\n", | |
"bond = pd.read_csv(\n", | |
" bonds_file, header=0, parse_dates=[\"Date\"], usecols=['Date','Adj Close'])\n", | |
"bond.head()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 25, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:13:44.421014Z", | |
"start_time": "2018-10-06T17:13:44.417063Z" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"bond.rename(columns={\"Adj Close\": \"bond\"},inplace=True)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 26, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:13:44.492859Z", | |
"start_time": "2018-10-06T17:13:44.423013Z" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>bond</th>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>Date</th>\n", | |
" <th></th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>2006-02-27</th>\n", | |
" <td>59.428551</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-02-28</th>\n", | |
" <td>59.722687</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-03-01</th>\n", | |
" <td>59.361893</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-03-02</th>\n", | |
" <td>58.948498</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-03-03</th>\n", | |
" <td>58.607433</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" bond\n", | |
"Date \n", | |
"2006-02-27 59.428551\n", | |
"2006-02-28 59.722687\n", | |
"2006-03-01 59.361893\n", | |
"2006-03-02 58.948498\n", | |
"2006-03-03 58.607433" | |
] | |
}, | |
"execution_count": 26, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"bond=bond[(bond.Date>='2006-02-27')]\n", | |
"bond.index=bond.Date\n", | |
"bond.drop(columns=['Date'],inplace=True)\n", | |
"bond.head()\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 27, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:13:44.526730Z", | |
"start_time": "2018-10-06T17:13:44.494898Z" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>Date</th>\n", | |
" <th>i</th>\n", | |
" <th>quote_date</th>\n", | |
" <th>expiration</th>\n", | |
" <th>strike</th>\n", | |
" <th>trade_volume</th>\n", | |
" <th>price</th>\n", | |
" <th>newMonth</th>\n", | |
" <th>targetExpiration</th>\n", | |
" <th>ExpDiff</th>\n", | |
" <th>mid_underlying</th>\n", | |
" <th>futures</th>\n", | |
" <th>strikeTarget</th>\n", | |
" <th>strikeLocation</th>\n", | |
" <th>StrikeDiff</th>\n", | |
" <th>entry</th>\n", | |
" <th>exit</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>714</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>9.90</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.32</td>\n", | |
" <td>22.5</td>\n", | |
" <td>11.32</td>\n", | |
" <td>714</td>\n", | |
" <td>11.18</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>2006-04-20</td>\n", | |
" <td>721</td>\n", | |
" <td>2006-04-20</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>12.55</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.64</td>\n", | |
" <td>12.5</td>\n", | |
" <td>11.32</td>\n", | |
" <td>714</td>\n", | |
" <td>11.18</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2</th>\n", | |
" <td>2006-04-21</td>\n", | |
" <td>729</td>\n", | |
" <td>2006-04-21</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>12.35</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.59</td>\n", | |
" <td>12.5</td>\n", | |
" <td>11.32</td>\n", | |
" <td>714</td>\n", | |
" <td>11.18</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>3</th>\n", | |
" <td>2006-04-24</td>\n", | |
" <td>768</td>\n", | |
" <td>2006-04-24</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>20.0</td>\n", | |
" <td>12.45</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.75</td>\n", | |
" <td>12.5</td>\n", | |
" <td>11.32</td>\n", | |
" <td>714</td>\n", | |
" <td>11.18</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>4</th>\n", | |
" <td>2006-04-25</td>\n", | |
" <td>807</td>\n", | |
" <td>2006-04-25</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>9.90</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.76</td>\n", | |
" <td>12.5</td>\n", | |
" <td>11.32</td>\n", | |
" <td>714</td>\n", | |
" <td>11.18</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Date i quote_date expiration strike trade_volume price \\\n", | |
"0 2006-04-19 714 2006-04-19 2006-05-17 22.5 0.0 9.90 \n", | |
"1 2006-04-20 721 2006-04-20 2006-05-17 22.5 0.0 12.55 \n", | |
"2 2006-04-21 729 2006-04-21 2006-05-17 22.5 0.0 12.35 \n", | |
"3 2006-04-24 768 2006-04-24 2006-05-17 22.5 20.0 12.45 \n", | |
"4 2006-04-25 807 2006-04-25 2006-05-17 22.5 0.0 9.90 \n", | |
"\n", | |
" newMonth targetExpiration ExpDiff mid_underlying \\\n", | |
"0 2006-04-19 2006-11-05 172 days 00:00:00.000000000 11.32 \n", | |
"1 2006-04-19 2006-11-05 172 days 00:00:00.000000000 11.64 \n", | |
"2 2006-04-19 2006-11-05 172 days 00:00:00.000000000 11.59 \n", | |
"3 2006-04-19 2006-11-05 172 days 00:00:00.000000000 11.75 \n", | |
"4 2006-04-19 2006-11-05 172 days 00:00:00.000000000 11.76 \n", | |
"\n", | |
" futures strikeTarget strikeLocation StrikeDiff entry exit \n", | |
"0 22.5 11.32 714 11.18 False False \n", | |
"1 12.5 11.32 714 11.18 False False \n", | |
"2 12.5 11.32 714 11.18 False False \n", | |
"3 12.5 11.32 714 11.18 False False \n", | |
"4 12.5 11.32 714 11.18 False False " | |
] | |
}, | |
"execution_count": 27, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"#puts_file='../data/Options/vxxRolling_puts.csv'\n", | |
"puts_file = '../data/Options/vix_rolling_puts.csv'\n", | |
"\n", | |
"puts = pd.read_csv(\n", | |
" puts_file,\n", | |
" header=0,\n", | |
" parse_dates=[\n", | |
" \"quote_date\",\n", | |
" \"expiration\",\n", | |
" \"newMonth\",\n", | |
" \"targetExpiration\",\n", | |
" ])\n", | |
"puts.head()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 28, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:13:44.625466Z", | |
"start_time": "2018-10-06T17:13:44.528725Z" | |
}, | |
"scrolled": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>Date</th>\n", | |
" <th>i</th>\n", | |
" <th>quote_date</th>\n", | |
" <th>expiration</th>\n", | |
" <th>strike</th>\n", | |
" <th>trade_volume</th>\n", | |
" <th>price</th>\n", | |
" <th>newMonth</th>\n", | |
" <th>targetExpiration</th>\n", | |
" <th>ExpDiff</th>\n", | |
" <th>mid_underlying</th>\n", | |
" <th>futures</th>\n", | |
" <th>strikeTarget</th>\n", | |
" <th>strikeLocation</th>\n", | |
" <th>StrikeDiff</th>\n", | |
" <th>entry</th>\n", | |
" <th>exit</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>714</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>9.90</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.32</td>\n", | |
" <td>22.5</td>\n", | |
" <td>11.32</td>\n", | |
" <td>714</td>\n", | |
" <td>11.18</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>2006-04-20</td>\n", | |
" <td>721</td>\n", | |
" <td>2006-04-20</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>12.55</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.64</td>\n", | |
" <td>12.5</td>\n", | |
" <td>11.32</td>\n", | |
" <td>714</td>\n", | |
" <td>11.18</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2</th>\n", | |
" <td>2006-04-21</td>\n", | |
" <td>729</td>\n", | |
" <td>2006-04-21</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>12.35</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.59</td>\n", | |
" <td>12.5</td>\n", | |
" <td>11.32</td>\n", | |
" <td>714</td>\n", | |
" <td>11.18</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>3</th>\n", | |
" <td>2006-04-24</td>\n", | |
" <td>768</td>\n", | |
" <td>2006-04-24</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>20.0</td>\n", | |
" <td>12.45</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.75</td>\n", | |
" <td>12.5</td>\n", | |
" <td>11.32</td>\n", | |
" <td>714</td>\n", | |
" <td>11.18</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>4</th>\n", | |
" <td>2006-04-25</td>\n", | |
" <td>807</td>\n", | |
" <td>2006-04-25</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>9.90</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.76</td>\n", | |
" <td>12.5</td>\n", | |
" <td>11.32</td>\n", | |
" <td>714</td>\n", | |
" <td>11.18</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Date i quote_date expiration strike trade_volume price \\\n", | |
"0 2006-04-19 714 2006-04-19 2006-05-17 22.5 0.0 9.90 \n", | |
"1 2006-04-20 721 2006-04-20 2006-05-17 22.5 0.0 12.55 \n", | |
"2 2006-04-21 729 2006-04-21 2006-05-17 22.5 0.0 12.35 \n", | |
"3 2006-04-24 768 2006-04-24 2006-05-17 22.5 20.0 12.45 \n", | |
"4 2006-04-25 807 2006-04-25 2006-05-17 22.5 0.0 9.90 \n", | |
"\n", | |
" newMonth targetExpiration ExpDiff mid_underlying \\\n", | |
"0 2006-04-19 2006-11-05 172 days 00:00:00.000000000 11.32 \n", | |
"1 2006-04-19 2006-11-05 172 days 00:00:00.000000000 11.64 \n", | |
"2 2006-04-19 2006-11-05 172 days 00:00:00.000000000 11.59 \n", | |
"3 2006-04-19 2006-11-05 172 days 00:00:00.000000000 11.75 \n", | |
"4 2006-04-19 2006-11-05 172 days 00:00:00.000000000 11.76 \n", | |
"\n", | |
" futures strikeTarget strikeLocation StrikeDiff entry exit \n", | |
"0 22.5 11.32 714 11.18 False False \n", | |
"1 12.5 11.32 714 11.18 False False \n", | |
"2 12.5 11.32 714 11.18 False False \n", | |
"3 12.5 11.32 714 11.18 False False \n", | |
"4 12.5 11.32 714 11.18 False False " | |
] | |
}, | |
"execution_count": 28, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"filter1=puts['entry'].isin([False]) \n", | |
"filter2=puts['exit'].isin([False]) \n", | |
"dealing_days=puts[(filter1)| (filter2)]\n", | |
"\n", | |
"dealing_days.to_csv('../data/Options/strikes.csv')\n", | |
"dealing_days.head()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 29, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:13:44.659375Z", | |
"start_time": "2018-10-06T17:13:44.627460Z" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>Date</th>\n", | |
" <th>i</th>\n", | |
" <th>quote_date</th>\n", | |
" <th>expiration</th>\n", | |
" <th>strike</th>\n", | |
" <th>trade_volume</th>\n", | |
" <th>price</th>\n", | |
" <th>newMonth</th>\n", | |
" <th>targetExpiration</th>\n", | |
" <th>ExpDiff</th>\n", | |
" <th>mid_underlying</th>\n", | |
" <th>futures</th>\n", | |
" <th>strikeTarget</th>\n", | |
" <th>strikeLocation</th>\n", | |
" <th>StrikeDiff</th>\n", | |
" <th>entry</th>\n", | |
" <th>exit</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>714</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.075</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.32</td>\n", | |
" <td>22.5</td>\n", | |
" <td>22.64</td>\n", | |
" <td>714</td>\n", | |
" <td>0.14</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>2006-04-20</td>\n", | |
" <td>721</td>\n", | |
" <td>2006-04-20</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.075</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.64</td>\n", | |
" <td>12.5</td>\n", | |
" <td>22.64</td>\n", | |
" <td>714</td>\n", | |
" <td>0.14</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2</th>\n", | |
" <td>2006-04-21</td>\n", | |
" <td>729</td>\n", | |
" <td>2006-04-21</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.075</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.59</td>\n", | |
" <td>12.5</td>\n", | |
" <td>22.64</td>\n", | |
" <td>714</td>\n", | |
" <td>0.14</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>3</th>\n", | |
" <td>2006-04-24</td>\n", | |
" <td>768</td>\n", | |
" <td>2006-04-24</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.075</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.75</td>\n", | |
" <td>12.5</td>\n", | |
" <td>22.64</td>\n", | |
" <td>714</td>\n", | |
" <td>0.14</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>4</th>\n", | |
" <td>2006-04-25</td>\n", | |
" <td>807</td>\n", | |
" <td>2006-04-25</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.050</td>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.76</td>\n", | |
" <td>12.5</td>\n", | |
" <td>22.64</td>\n", | |
" <td>714</td>\n", | |
" <td>0.14</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Date i quote_date expiration strike trade_volume price \\\n", | |
"0 2006-04-19 714 2006-04-19 2006-05-17 22.5 0.0 0.075 \n", | |
"1 2006-04-20 721 2006-04-20 2006-05-17 22.5 0.0 0.075 \n", | |
"2 2006-04-21 729 2006-04-21 2006-05-17 22.5 0.0 0.075 \n", | |
"3 2006-04-24 768 2006-04-24 2006-05-17 22.5 0.0 0.075 \n", | |
"4 2006-04-25 807 2006-04-25 2006-05-17 22.5 0.0 0.050 \n", | |
"\n", | |
" newMonth targetExpiration ExpDiff mid_underlying \\\n", | |
"0 2006-04-19 2006-11-05 172 days 00:00:00.000000000 11.32 \n", | |
"1 2006-04-19 2006-11-05 172 days 00:00:00.000000000 11.64 \n", | |
"2 2006-04-19 2006-11-05 172 days 00:00:00.000000000 11.59 \n", | |
"3 2006-04-19 2006-11-05 172 days 00:00:00.000000000 11.75 \n", | |
"4 2006-04-19 2006-11-05 172 days 00:00:00.000000000 11.76 \n", | |
"\n", | |
" futures strikeTarget strikeLocation StrikeDiff entry exit \n", | |
"0 22.5 22.64 714 0.14 False False \n", | |
"1 12.5 22.64 714 0.14 False False \n", | |
"2 12.5 22.64 714 0.14 False False \n", | |
"3 12.5 22.64 714 0.14 False False \n", | |
"4 12.5 22.64 714 0.14 False False " | |
] | |
}, | |
"execution_count": 29, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"#calls_file='../data/Options/vxxRolling_calls.csv'\n", | |
"calls_file='../data/Options/vix_rolling_calls.csv'\n", | |
"\n", | |
"calls = pd.read_csv(\n", | |
" calls_file,\n", | |
" header=0,\n", | |
" parse_dates=[\n", | |
" \"quote_date\",\n", | |
" \"expiration\",\n", | |
" \"newMonth\",\n", | |
" \"targetExpiration\",\n", | |
" ])\n", | |
"calls.head()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 30, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:13:44.679322Z", | |
"start_time": "2018-10-06T17:13:44.661370Z" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>put_quote_date</th>\n", | |
" <th>put_expiration</th>\n", | |
" <th>put_strike</th>\n", | |
" <th>put_trade_volume</th>\n", | |
" <th>put_price</th>\n", | |
" <th>put_targetExpiration</th>\n", | |
" <th>put_ExpDiff</th>\n", | |
" <th>put_mid_underlying</th>\n", | |
" <th>futures</th>\n", | |
" <th>put_entry</th>\n", | |
" <th>put_exit</th>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>put_quote_date</th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>2006-04-19</th>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>9.90</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.32</td>\n", | |
" <td>22.5</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-04-20</th>\n", | |
" <td>2006-04-20</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>12.55</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.64</td>\n", | |
" <td>12.5</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-04-21</th>\n", | |
" <td>2006-04-21</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>12.35</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.59</td>\n", | |
" <td>12.5</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-04-24</th>\n", | |
" <td>2006-04-24</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>20.0</td>\n", | |
" <td>12.45</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.75</td>\n", | |
" <td>12.5</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-04-25</th>\n", | |
" <td>2006-04-25</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>9.90</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.76</td>\n", | |
" <td>12.5</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" put_quote_date put_expiration put_strike put_trade_volume \\\n", | |
"put_quote_date \n", | |
"2006-04-19 2006-04-19 2006-05-17 22.5 0.0 \n", | |
"2006-04-20 2006-04-20 2006-05-17 22.5 0.0 \n", | |
"2006-04-21 2006-04-21 2006-05-17 22.5 0.0 \n", | |
"2006-04-24 2006-04-24 2006-05-17 22.5 20.0 \n", | |
"2006-04-25 2006-04-25 2006-05-17 22.5 0.0 \n", | |
"\n", | |
" put_price put_targetExpiration put_ExpDiff \\\n", | |
"put_quote_date \n", | |
"2006-04-19 9.90 2006-11-05 172 days 00:00:00.000000000 \n", | |
"2006-04-20 12.55 2006-11-05 172 days 00:00:00.000000000 \n", | |
"2006-04-21 12.35 2006-11-05 172 days 00:00:00.000000000 \n", | |
"2006-04-24 12.45 2006-11-05 172 days 00:00:00.000000000 \n", | |
"2006-04-25 9.90 2006-11-05 172 days 00:00:00.000000000 \n", | |
"\n", | |
" put_mid_underlying futures put_entry put_exit \n", | |
"put_quote_date \n", | |
"2006-04-19 11.32 22.5 False False \n", | |
"2006-04-20 11.64 12.5 False False \n", | |
"2006-04-21 11.59 12.5 False False \n", | |
"2006-04-24 11.75 12.5 False False \n", | |
"2006-04-25 11.76 12.5 False False " | |
] | |
}, | |
"execution_count": 30, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"put_prices = puts.filter(\n", | |
" [\n", | |
" 'quote_date', 'expiration', 'strike', 'trade_volume', 'price',\n", | |
" 'targetExpiration', 'ExpDiff', 'mid_underlying','futures','entry', 'exit'\n", | |
" ],\n", | |
" axis=1)\n", | |
"put_prices.rename(\n", | |
" columns={\n", | |
" 'quote_date': 'put_quote_date',\n", | |
" 'expiration': 'put_expiration',\n", | |
" 'strike': 'put_strike',\n", | |
" 'trade_volume': 'put_trade_volume',\n", | |
" 'price': 'put_price',\n", | |
" 'targetExpiration': 'put_targetExpiration',\n", | |
" 'ExpDiff': 'put_ExpDiff',\n", | |
" 'mid_underlying': 'put_mid_underlying',\n", | |
" 'futures':'futures',\n", | |
" 'entry': 'put_entry',\n", | |
" 'exit': 'put_exit'\n", | |
" },\n", | |
" inplace=True)\n", | |
"put_prices.index = put_prices.put_quote_date\n", | |
"put_prices.head()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 31, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:13:44.699269Z", | |
"start_time": "2018-10-06T17:13:44.680319Z" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>call_quote_date</th>\n", | |
" <th>call_expiration</th>\n", | |
" <th>call_strike</th>\n", | |
" <th>call_trade_volume</th>\n", | |
" <th>call_price</th>\n", | |
" <th>call_targetExpiration</th>\n", | |
" <th>call_ExpDiff</th>\n", | |
" <th>call_mid_underlying</th>\n", | |
" <th>futures</th>\n", | |
" <th>call_entry</th>\n", | |
" <th>call_exit</th>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>call_quote_date</th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>2006-04-19</th>\n", | |
" <td>2006-04-19</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.075</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.32</td>\n", | |
" <td>22.5</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-04-20</th>\n", | |
" <td>2006-04-20</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.075</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.64</td>\n", | |
" <td>12.5</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-04-21</th>\n", | |
" <td>2006-04-21</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.075</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.59</td>\n", | |
" <td>12.5</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-04-24</th>\n", | |
" <td>2006-04-24</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.075</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.75</td>\n", | |
" <td>12.5</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-04-25</th>\n", | |
" <td>2006-04-25</td>\n", | |
" <td>2006-05-17</td>\n", | |
" <td>22.5</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.050</td>\n", | |
" <td>2006-11-05</td>\n", | |
" <td>172 days 00:00:00.000000000</td>\n", | |
" <td>11.76</td>\n", | |
" <td>12.5</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" call_quote_date call_expiration call_strike \\\n", | |
"call_quote_date \n", | |
"2006-04-19 2006-04-19 2006-05-17 22.5 \n", | |
"2006-04-20 2006-04-20 2006-05-17 22.5 \n", | |
"2006-04-21 2006-04-21 2006-05-17 22.5 \n", | |
"2006-04-24 2006-04-24 2006-05-17 22.5 \n", | |
"2006-04-25 2006-04-25 2006-05-17 22.5 \n", | |
"\n", | |
" call_trade_volume call_price call_targetExpiration \\\n", | |
"call_quote_date \n", | |
"2006-04-19 0.0 0.075 2006-11-05 \n", | |
"2006-04-20 0.0 0.075 2006-11-05 \n", | |
"2006-04-21 0.0 0.075 2006-11-05 \n", | |
"2006-04-24 0.0 0.075 2006-11-05 \n", | |
"2006-04-25 0.0 0.050 2006-11-05 \n", | |
"\n", | |
" call_ExpDiff call_mid_underlying futures \\\n", | |
"call_quote_date \n", | |
"2006-04-19 172 days 00:00:00.000000000 11.32 22.5 \n", | |
"2006-04-20 172 days 00:00:00.000000000 11.64 12.5 \n", | |
"2006-04-21 172 days 00:00:00.000000000 11.59 12.5 \n", | |
"2006-04-24 172 days 00:00:00.000000000 11.75 12.5 \n", | |
"2006-04-25 172 days 00:00:00.000000000 11.76 12.5 \n", | |
"\n", | |
" call_entry call_exit \n", | |
"call_quote_date \n", | |
"2006-04-19 False False \n", | |
"2006-04-20 False False \n", | |
"2006-04-21 False False \n", | |
"2006-04-24 False False \n", | |
"2006-04-25 False False " | |
] | |
}, | |
"execution_count": 31, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"call_prices = calls.filter(\n", | |
" [\n", | |
" 'quote_date', 'expiration', 'strike', 'trade_volume', 'price',\n", | |
" 'targetExpiration', 'ExpDiff', 'mid_underlying', 'futures','entry', 'exit'\n", | |
" ],\n", | |
" axis=1)\n", | |
"call_prices.rename(\n", | |
" columns={\n", | |
" 'quote_date': 'call_quote_date',\n", | |
" 'expiration': 'call_expiration',\n", | |
" 'strike': 'call_strike',\n", | |
" 'trade_volume': 'call_trade_volume',\n", | |
" 'price': 'call_price',\n", | |
" 'targetExpiration': 'call_targetExpiration',\n", | |
" 'ExpDiff': 'call_ExpDiff',\n", | |
" 'mid_underlying': 'call_mid_underlying',\n", | |
" 'futures': 'futures',\n", | |
" 'entry': 'call_entry',\n", | |
" 'exit': 'call_exit'\n", | |
" },\n", | |
" inplace=True)\n", | |
"call_prices.index = call_prices.call_quote_date\n", | |
"call_prices.head()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 32, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:13:44.854853Z", | |
"start_time": "2018-10-06T17:13:44.701263Z" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>put_quote_date</th>\n", | |
" <th>put_expiration</th>\n", | |
" <th>put_strike</th>\n", | |
" <th>put_trade_volume</th>\n", | |
" <th>put_price</th>\n", | |
" <th>put_targetExpiration</th>\n", | |
" <th>put_ExpDiff</th>\n", | |
" <th>put_mid_underlying</th>\n", | |
" <th>futures</th>\n", | |
" <th>put_entry</th>\n", | |
" <th>put_exit</th>\n", | |
" <th>call_quote_date</th>\n", | |
" <th>call_expiration</th>\n", | |
" <th>call_strike</th>\n", | |
" <th>call_trade_volume</th>\n", | |
" <th>call_price</th>\n", | |
" <th>call_targetExpiration</th>\n", | |
" <th>call_ExpDiff</th>\n", | |
" <th>call_mid_underlying</th>\n", | |
" <th>futures</th>\n", | |
" <th>call_entry</th>\n", | |
" <th>call_exit</th>\n", | |
" <th>bond</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>2006-02-27</th>\n", | |
" <td>NaT</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>59.428551</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-02-28</th>\n", | |
" <td>NaT</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>59.722687</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-03-01</th>\n", | |
" <td>NaT</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>59.361893</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-03-02</th>\n", | |
" <td>NaT</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>58.948498</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-03-03</th>\n", | |
" <td>NaT</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaT</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>58.607433</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" put_quote_date put_expiration put_strike put_trade_volume \\\n", | |
"2006-02-27 NaT NaT NaN NaN \n", | |
"2006-02-28 NaT NaT NaN NaN \n", | |
"2006-03-01 NaT NaT NaN NaN \n", | |
"2006-03-02 NaT NaT NaN NaN \n", | |
"2006-03-03 NaT NaT NaN NaN \n", | |
"\n", | |
" put_price put_targetExpiration put_ExpDiff put_mid_underlying \\\n", | |
"2006-02-27 NaN NaT NaN NaN \n", | |
"2006-02-28 NaN NaT NaN NaN \n", | |
"2006-03-01 NaN NaT NaN NaN \n", | |
"2006-03-02 NaN NaT NaN NaN \n", | |
"2006-03-03 NaN NaT NaN NaN \n", | |
"\n", | |
" futures put_entry put_exit call_quote_date call_expiration \\\n", | |
"2006-02-27 NaN NaN NaN NaT NaT \n", | |
"2006-02-28 NaN NaN NaN NaT NaT \n", | |
"2006-03-01 NaN NaN NaN NaT NaT \n", | |
"2006-03-02 NaN NaN NaN NaT NaT \n", | |
"2006-03-03 NaN NaN NaN NaT NaT \n", | |
"\n", | |
" call_strike call_trade_volume call_price call_targetExpiration \\\n", | |
"2006-02-27 NaN NaN NaN NaT \n", | |
"2006-02-28 NaN NaN NaN NaT \n", | |
"2006-03-01 NaN NaN NaN NaT \n", | |
"2006-03-02 NaN NaN NaN NaT \n", | |
"2006-03-03 NaN NaN NaN NaT \n", | |
"\n", | |
" call_ExpDiff call_mid_underlying futures call_entry call_exit \\\n", | |
"2006-02-27 NaN NaN NaN NaN NaN \n", | |
"2006-02-28 NaN NaN NaN NaN NaN \n", | |
"2006-03-01 NaN NaN NaN NaN NaN \n", | |
"2006-03-02 NaN NaN NaN NaN NaN \n", | |
"2006-03-03 NaN NaN NaN NaN NaN \n", | |
"\n", | |
" bond \n", | |
"2006-02-27 59.428551 \n", | |
"2006-02-28 59.722687 \n", | |
"2006-03-01 59.361893 \n", | |
"2006-03-02 58.948498 \n", | |
"2006-03-03 58.607433 " | |
] | |
}, | |
"execution_count": 32, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"combined = pd.concat([put_prices, call_prices,bond], axis=1, sort=False)\n", | |
"combined.to_csv('../data/Options/combined1.csv')\n", | |
"combined.head() #.fillna(method='ffill',inplace=True)\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 33, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:13:44.863829Z", | |
"start_time": "2018-10-06T17:13:44.855873Z" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"combined.fillna(method='ffill',inplace=True)\n", | |
"#combined" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 34, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:13:44.871808Z", | |
"start_time": "2018-10-06T17:13:44.864847Z" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"mask = combined['call_price'].isnull()\n", | |
"#print(combined.loc[mask].tail())" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 35, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:13:44.882778Z", | |
"start_time": "2018-10-06T17:13:44.872819Z" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"mask = combined['put_price'].isnull()\n", | |
"#print(combined.loc[mask].tail())" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 36, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:13:45.053322Z", | |
"start_time": "2018-10-06T17:13:44.883776Z" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>put_quote_date</th>\n", | |
" <th>put_expiration</th>\n", | |
" <th>put_strike</th>\n", | |
" <th>put_trade_volume</th>\n", | |
" <th>put_price</th>\n", | |
" <th>put_targetExpiration</th>\n", | |
" <th>put_ExpDiff</th>\n", | |
" <th>put_mid_underlying</th>\n", | |
" <th>futures</th>\n", | |
" <th>put_entry</th>\n", | |
" <th>put_exit</th>\n", | |
" <th>call_quote_date</th>\n", | |
" <th>call_expiration</th>\n", | |
" <th>call_strike</th>\n", | |
" <th>call_trade_volume</th>\n", | |
" <th>call_price</th>\n", | |
" <th>call_targetExpiration</th>\n", | |
" <th>call_ExpDiff</th>\n", | |
" <th>call_mid_underlying</th>\n", | |
" <th>futures</th>\n", | |
" <th>call_entry</th>\n", | |
" <th>call_exit</th>\n", | |
" <th>bond</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>2018-09-17</th>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>12.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>16.0</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>24.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>1.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>16.0</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>118.550003</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2018-09-18</th>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>12.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>16.0</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>24.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>1.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>16.0</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>117.309998</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2018-09-19</th>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>12.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>16.0</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>24.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>1.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>16.0</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>116.610001</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2018-09-20</th>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>12.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>16.0</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>24.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>1.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>16.0</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>117.150002</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2018-09-21</th>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>12.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>16.0</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>24.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>1.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>16.0</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>117.099998</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" put_quote_date put_expiration put_strike put_trade_volume \\\n", | |
"2018-09-17 2018-09-05 2019-01-16 12.0 0.0 \n", | |
"2018-09-18 2018-09-05 2019-01-16 12.0 0.0 \n", | |
"2018-09-19 2018-09-05 2019-01-16 12.0 0.0 \n", | |
"2018-09-20 2018-09-05 2019-01-16 12.0 0.0 \n", | |
"2018-09-21 2018-09-05 2019-01-16 12.0 0.0 \n", | |
"\n", | |
" put_price put_targetExpiration put_ExpDiff \\\n", | |
"2018-09-17 0.3 2019-03-10 53 days 00:00:00.000000000 \n", | |
"2018-09-18 0.3 2019-03-10 53 days 00:00:00.000000000 \n", | |
"2018-09-19 0.3 2019-03-10 53 days 00:00:00.000000000 \n", | |
"2018-09-20 0.3 2019-03-10 53 days 00:00:00.000000000 \n", | |
"2018-09-21 0.3 2019-03-10 53 days 00:00:00.000000000 \n", | |
"\n", | |
" put_mid_underlying futures put_entry put_exit call_quote_date \\\n", | |
"2018-09-17 13.91 16.0 False False 2018-09-05 \n", | |
"2018-09-18 13.91 16.0 False False 2018-09-05 \n", | |
"2018-09-19 13.91 16.0 False False 2018-09-05 \n", | |
"2018-09-20 13.91 16.0 False False 2018-09-05 \n", | |
"2018-09-21 13.91 16.0 False False 2018-09-05 \n", | |
"\n", | |
" call_expiration call_strike call_trade_volume call_price \\\n", | |
"2018-09-17 2019-01-16 24.0 0.0 1.3 \n", | |
"2018-09-18 2019-01-16 24.0 0.0 1.3 \n", | |
"2018-09-19 2019-01-16 24.0 0.0 1.3 \n", | |
"2018-09-20 2019-01-16 24.0 0.0 1.3 \n", | |
"2018-09-21 2019-01-16 24.0 0.0 1.3 \n", | |
"\n", | |
" call_targetExpiration call_ExpDiff \\\n", | |
"2018-09-17 2019-03-10 53 days 00:00:00.000000000 \n", | |
"2018-09-18 2019-03-10 53 days 00:00:00.000000000 \n", | |
"2018-09-19 2019-03-10 53 days 00:00:00.000000000 \n", | |
"2018-09-20 2019-03-10 53 days 00:00:00.000000000 \n", | |
"2018-09-21 2019-03-10 53 days 00:00:00.000000000 \n", | |
"\n", | |
" call_mid_underlying futures call_entry call_exit bond \n", | |
"2018-09-17 13.91 16.0 False False 118.550003 \n", | |
"2018-09-18 13.91 16.0 False False 117.309998 \n", | |
"2018-09-19 13.91 16.0 False False 116.610001 \n", | |
"2018-09-20 13.91 16.0 False False 117.150002 \n", | |
"2018-09-21 13.91 16.0 False False 117.099998 " | |
] | |
}, | |
"execution_count": 36, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"combined.to_csv('../data/Options/combined2.csv')\n", | |
"combined.tail()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 37, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:17:20.950373Z", | |
"start_time": "2018-10-06T17:17:20.809750Z" | |
}, | |
"pixiedust": { | |
"displayParams": {} | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"#%%pixie_debugger\n", | |
"starting_capital = 100000.00\n", | |
"put_allocation =0.14\n", | |
"call_allocation =0.06\n", | |
"bond_allocation = 0.80\n", | |
"put_position = 0\n", | |
"put_position_value = 0\n", | |
"call_position = 0\n", | |
"call_position_value = 0\n", | |
"bond_position = 0\n", | |
"bond_position_value = 0\n", | |
"cash = 0.00\n", | |
"equity_curve = 0\n", | |
"new_cash = 0.00\n", | |
"temp_PnL = {}\n", | |
"\n", | |
"for i, row in enumerate(combined.itertuples(), 0):\n", | |
" if i == 0: start = False\n", | |
" if i == 0: equity_curve = starting_capital\n", | |
"\n", | |
" if (row.put_entry == True and row.call_entry == True and row.put_price > 0\n", | |
" and row.call_price > 0):\n", | |
" #if (combined.put_expiration[i]!=combined.put_expiration[i-1]):\n", | |
" start = True\n", | |
"\n", | |
" put_position = round((equity_curve * put_allocation) / row.put_price,\n", | |
" 0)\n", | |
" put_position_value = put_position * row.put_price\n", | |
"\n", | |
" call_position = round(\n", | |
" (equity_curve * call_allocation) / row.call_price, 0)\n", | |
" call_position_value = call_position * row.call_price\n", | |
"\n", | |
" bond_position = round((equity_curve * bond_allocation) / row.bond, 0)\n", | |
" bond_position_value = bond_position * row.bond\n", | |
"\n", | |
" cash = equity_curve - (\n", | |
" put_position_value + call_position_value + bond_position_value)\n", | |
" equity_curve = put_position_value + call_position_value + bond_position_value + cash\n", | |
"\n", | |
" temp_PnL[combined.index[i]] = [\n", | |
" i, row.put_quote_date, row.put_expiration, row.put_strike,\n", | |
" row.put_trade_volume, row.put_price, row.put_targetExpiration,\n", | |
" row.put_ExpDiff, row.put_mid_underlying, put_position,\n", | |
" put_position_value, row.put_entry, row.put_exit,row.futures,\n", | |
" row.call_quote_date, row.call_expiration, row.call_strike,\n", | |
" row.call_trade_volume, row.call_price, row.call_targetExpiration,\n", | |
" row.call_ExpDiff, row.call_mid_underlying, call_position,\n", | |
" call_position_value, row.call_entry, row.call_exit, bond_position,\n", | |
" bond_position_value, cash, equity_curve\n", | |
" ]\n", | |
" #print(i, row.price, 'position', position, 'position_value',\n", | |
" #position_value, 'cash', cash, 'equity_curve', equity_curve)\n", | |
" if start == True:\n", | |
" if row.put_entry == False and row.call_entry == False and row.put_price > 0 and row.call_price > 0:\n", | |
" put_position_value = put_position * row.put_price\n", | |
" call_position_value = call_position * row.call_price\n", | |
" bond_position_value = bond_position * row.bond\n", | |
" equity_curve = put_position_value + call_position_value + bond_position_value + cash\n", | |
" temp_PnL[combined.index[i]] = [\n", | |
" i, row.put_quote_date, row.put_expiration, row.put_strike,\n", | |
" row.put_trade_volume, row.put_price, row.put_targetExpiration,\n", | |
" row.put_ExpDiff, row.put_mid_underlying, put_position,\n", | |
" put_position_value, row.put_entry, row.put_exit,row.futures,\n", | |
" row.call_quote_date, row.call_expiration, row.call_strike,\n", | |
" row.call_trade_volume, row.call_price,\n", | |
" row.call_targetExpiration, row.call_ExpDiff,\n", | |
" row.call_mid_underlying, call_position, call_position_value,\n", | |
" row.call_entry, row.call_exit, bond_position,\n", | |
" bond_position_value, cash, equity_curve\n", | |
" ]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 38, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:17:21.368255Z", | |
"start_time": "2018-10-06T17:17:20.951371Z" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>i</th>\n", | |
" <th>put_quote_date</th>\n", | |
" <th>put_expiration</th>\n", | |
" <th>put_strike</th>\n", | |
" <th>put_trade_volume</th>\n", | |
" <th>put_price</th>\n", | |
" <th>put_targetExpiration</th>\n", | |
" <th>put_ExpDiff</th>\n", | |
" <th>put_mid_underlying</th>\n", | |
" <th>put_position</th>\n", | |
" <th>put_position_value</th>\n", | |
" <th>put_entry</th>\n", | |
" <th>put_exit</th>\n", | |
" <th>futures</th>\n", | |
" <th>call_quote_date</th>\n", | |
" <th>call_expiration</th>\n", | |
" <th>call_strike</th>\n", | |
" <th>call_trade_volume</th>\n", | |
" <th>call_price</th>\n", | |
" <th>call_targetExpiration</th>\n", | |
" <th>call_ExpDiff</th>\n", | |
" <th>call_mid_underlying</th>\n", | |
" <th>call_position</th>\n", | |
" <th>call_position_value</th>\n", | |
" <th>call_entry</th>\n", | |
" <th>call_exit</th>\n", | |
" <th>bond_position</th>\n", | |
" <th>bond_position_value</th>\n", | |
" <th>cash</th>\n", | |
" <th>equity_curve</th>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>Date</th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>2018-09-17</th>\n", | |
" <td>3161</td>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>12.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>225042.0</td>\n", | |
" <td>67512.6</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>16.0</td>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>24.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>1.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>28934.0</td>\n", | |
" <td>37614.2</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>3966.0</td>\n", | |
" <td>470169.311898</td>\n", | |
" <td>22.324904</td>\n", | |
" <td>575318.436802</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2018-09-18</th>\n", | |
" <td>3162</td>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>12.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>225042.0</td>\n", | |
" <td>67512.6</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>16.0</td>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>24.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>1.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>28934.0</td>\n", | |
" <td>37614.2</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>3966.0</td>\n", | |
" <td>465251.452068</td>\n", | |
" <td>22.324904</td>\n", | |
" <td>570400.576972</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2018-09-19</th>\n", | |
" <td>3163</td>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>12.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>225042.0</td>\n", | |
" <td>67512.6</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>16.0</td>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>24.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>1.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>28934.0</td>\n", | |
" <td>37614.2</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>3966.0</td>\n", | |
" <td>462475.263966</td>\n", | |
" <td>22.324904</td>\n", | |
" <td>567624.388870</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2018-09-20</th>\n", | |
" <td>3164</td>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>12.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>225042.0</td>\n", | |
" <td>67512.6</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>16.0</td>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>24.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>1.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>28934.0</td>\n", | |
" <td>37614.2</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>3966.0</td>\n", | |
" <td>464616.907932</td>\n", | |
" <td>22.324904</td>\n", | |
" <td>569766.032836</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2018-09-21</th>\n", | |
" <td>3165</td>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>12.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>225042.0</td>\n", | |
" <td>67512.6</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>16.0</td>\n", | |
" <td>2018-09-05</td>\n", | |
" <td>2019-01-16</td>\n", | |
" <td>24.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>1.3</td>\n", | |
" <td>2019-03-10</td>\n", | |
" <td>53 days 00:00:00.000000000</td>\n", | |
" <td>13.91</td>\n", | |
" <td>28934.0</td>\n", | |
" <td>37614.2</td>\n", | |
" <td>False</td>\n", | |
" <td>False</td>\n", | |
" <td>3966.0</td>\n", | |
" <td>464418.592068</td>\n", | |
" <td>22.324904</td>\n", | |
" <td>569567.716972</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" i put_quote_date put_expiration put_strike put_trade_volume \\\n", | |
"Date \n", | |
"2018-09-17 3161 2018-09-05 2019-01-16 12.0 0.0 \n", | |
"2018-09-18 3162 2018-09-05 2019-01-16 12.0 0.0 \n", | |
"2018-09-19 3163 2018-09-05 2019-01-16 12.0 0.0 \n", | |
"2018-09-20 3164 2018-09-05 2019-01-16 12.0 0.0 \n", | |
"2018-09-21 3165 2018-09-05 2019-01-16 12.0 0.0 \n", | |
"\n", | |
" put_price put_targetExpiration put_ExpDiff \\\n", | |
"Date \n", | |
"2018-09-17 0.3 2019-03-10 53 days 00:00:00.000000000 \n", | |
"2018-09-18 0.3 2019-03-10 53 days 00:00:00.000000000 \n", | |
"2018-09-19 0.3 2019-03-10 53 days 00:00:00.000000000 \n", | |
"2018-09-20 0.3 2019-03-10 53 days 00:00:00.000000000 \n", | |
"2018-09-21 0.3 2019-03-10 53 days 00:00:00.000000000 \n", | |
"\n", | |
" put_mid_underlying put_position put_position_value put_entry \\\n", | |
"Date \n", | |
"2018-09-17 13.91 225042.0 67512.6 False \n", | |
"2018-09-18 13.91 225042.0 67512.6 False \n", | |
"2018-09-19 13.91 225042.0 67512.6 False \n", | |
"2018-09-20 13.91 225042.0 67512.6 False \n", | |
"2018-09-21 13.91 225042.0 67512.6 False \n", | |
"\n", | |
" put_exit futures call_quote_date call_expiration call_strike \\\n", | |
"Date \n", | |
"2018-09-17 False 16.0 2018-09-05 2019-01-16 24.0 \n", | |
"2018-09-18 False 16.0 2018-09-05 2019-01-16 24.0 \n", | |
"2018-09-19 False 16.0 2018-09-05 2019-01-16 24.0 \n", | |
"2018-09-20 False 16.0 2018-09-05 2019-01-16 24.0 \n", | |
"2018-09-21 False 16.0 2018-09-05 2019-01-16 24.0 \n", | |
"\n", | |
" call_trade_volume call_price call_targetExpiration \\\n", | |
"Date \n", | |
"2018-09-17 0.0 1.3 2019-03-10 \n", | |
"2018-09-18 0.0 1.3 2019-03-10 \n", | |
"2018-09-19 0.0 1.3 2019-03-10 \n", | |
"2018-09-20 0.0 1.3 2019-03-10 \n", | |
"2018-09-21 0.0 1.3 2019-03-10 \n", | |
"\n", | |
" call_ExpDiff call_mid_underlying call_position \\\n", | |
"Date \n", | |
"2018-09-17 53 days 00:00:00.000000000 13.91 28934.0 \n", | |
"2018-09-18 53 days 00:00:00.000000000 13.91 28934.0 \n", | |
"2018-09-19 53 days 00:00:00.000000000 13.91 28934.0 \n", | |
"2018-09-20 53 days 00:00:00.000000000 13.91 28934.0 \n", | |
"2018-09-21 53 days 00:00:00.000000000 13.91 28934.0 \n", | |
"\n", | |
" call_position_value call_entry call_exit bond_position \\\n", | |
"Date \n", | |
"2018-09-17 37614.2 False False 3966.0 \n", | |
"2018-09-18 37614.2 False False 3966.0 \n", | |
"2018-09-19 37614.2 False False 3966.0 \n", | |
"2018-09-20 37614.2 False False 3966.0 \n", | |
"2018-09-21 37614.2 False False 3966.0 \n", | |
"\n", | |
" bond_position_value cash equity_curve \n", | |
"Date \n", | |
"2018-09-17 470169.311898 22.324904 575318.436802 \n", | |
"2018-09-18 465251.452068 22.324904 570400.576972 \n", | |
"2018-09-19 462475.263966 22.324904 567624.388870 \n", | |
"2018-09-20 464616.907932 22.324904 569766.032836 \n", | |
"2018-09-21 464418.592068 22.324904 569567.716972 " | |
] | |
}, | |
"execution_count": 38, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"PL = pd.DataFrame(temp_PnL).T.fillna(method='ffill')\n", | |
"PL.index.name = 'Date'\n", | |
"PL.columns = [\n", | |
" 'i', 'put_quote_date', 'put_expiration', 'put_strike', 'put_trade_volume',\n", | |
" 'put_price', 'put_targetExpiration', 'put_ExpDiff', 'put_mid_underlying',\n", | |
" 'put_position', 'put_position_value', 'put_entry', 'put_exit','futures',\n", | |
" 'call_quote_date', 'call_expiration', 'call_strike', 'call_trade_volume',\n", | |
" 'call_price', 'call_targetExpiration', 'call_ExpDiff',\n", | |
" 'call_mid_underlying', 'call_position', 'call_position_value',\n", | |
" 'call_entry', 'call_exit', 'bond_position', 'bond_position_value', 'cash',\n", | |
" 'equity_curve'\n", | |
"]\n", | |
"\n", | |
"PL.to_csv('../data/Options/vxxPnL.csv')\n", | |
"PL.tail()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 39, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:17:23.313090Z", | |
"start_time": "2018-10-06T17:17:23.309025Z" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"#because the is_list_like is moved to pandas.api.types\n", | |
"pd.core.common.is_list_like = pd.api.types.is_list_like\n", | |
"import ffn" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 40, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:17:23.330979Z", | |
"start_time": "2018-10-06T17:17:23.315010Z" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>equity_curve</th>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>Date</th>\n", | |
" <th></th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>2006-05-17</th>\n", | |
" <td>100000.0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-05-18</th>\n", | |
" <td>100000.0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-05-19</th>\n", | |
" <td>100000.0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-05-22</th>\n", | |
" <td>100000.0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-05-23</th>\n", | |
" <td>100000.0</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" equity_curve\n", | |
"Date \n", | |
"2006-05-17 100000.0\n", | |
"2006-05-18 100000.0\n", | |
"2006-05-19 100000.0\n", | |
"2006-05-22 100000.0\n", | |
"2006-05-23 100000.0" | |
] | |
}, | |
"execution_count": 40, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"option_series=PL[['equity_curve']].copy()\n", | |
"option_series.head()\n", | |
"#new = old[['A', 'C', 'D']].copy()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 41, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:17:23.346925Z", | |
"start_time": "2018-10-06T17:17:23.332962Z" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>Options</th>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>Date</th>\n", | |
" <th></th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>2006-05-17</th>\n", | |
" <td>100000.0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-05-18</th>\n", | |
" <td>100000.0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-05-19</th>\n", | |
" <td>100000.0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-05-22</th>\n", | |
" <td>100000.0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2006-05-23</th>\n", | |
" <td>100000.0</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Options\n", | |
"Date \n", | |
"2006-05-17 100000.0\n", | |
"2006-05-18 100000.0\n", | |
"2006-05-19 100000.0\n", | |
"2006-05-22 100000.0\n", | |
"2006-05-23 100000.0" | |
] | |
}, | |
"execution_count": 41, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"option_series.rename(columns={'equity_curve': 'Options'}, inplace=True)\n", | |
"option_series.head()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 42, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:17:23.421724Z", | |
"start_time": "2018-10-06T17:17:23.351911Z" | |
}, | |
"scrolled": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"/* Put everything inside the global mpl namespace */\n", | |
"window.mpl = {};\n", | |
"\n", | |
"\n", | |
"mpl.get_websocket_type = function() {\n", | |
" if (typeof(WebSocket) !== 'undefined') {\n", | |
" return WebSocket;\n", | |
" } else if (typeof(MozWebSocket) !== 'undefined') {\n", | |
" return MozWebSocket;\n", | |
" } else {\n", | |
" alert('Your browser does not have WebSocket support.' +\n", | |
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", | |
" 'Firefox 4 and 5 are also supported but you ' +\n", | |
" 'have to enable WebSockets in about:config.');\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", | |
" this.id = figure_id;\n", | |
"\n", | |
" this.ws = websocket;\n", | |
"\n", | |
" this.supports_binary = (this.ws.binaryType != undefined);\n", | |
"\n", | |
" if (!this.supports_binary) {\n", | |
" var warnings = document.getElementById(\"mpl-warnings\");\n", | |
" if (warnings) {\n", | |
" warnings.style.display = 'block';\n", | |
" warnings.textContent = (\n", | |
" \"This browser does not support binary websocket messages. \" +\n", | |
" \"Performance may be slow.\");\n", | |
" }\n", | |
" }\n", | |
"\n", | |
" this.imageObj = new Image();\n", | |
"\n", | |
" this.context = undefined;\n", | |
" this.message = undefined;\n", | |
" this.canvas = undefined;\n", | |
" this.rubberband_canvas = undefined;\n", | |
" this.rubberband_context = undefined;\n", | |
" this.format_dropdown = undefined;\n", | |
"\n", | |
" this.image_mode = 'full';\n", | |
"\n", | |
" this.root = $('<div/>');\n", | |
" this._root_extra_style(this.root)\n", | |
" this.root.attr('style', 'display: inline-block');\n", | |
"\n", | |
" $(parent_element).append(this.root);\n", | |
"\n", | |
" this._init_header(this);\n", | |
" this._init_canvas(this);\n", | |
" this._init_toolbar(this);\n", | |
"\n", | |
" var fig = this;\n", | |
"\n", | |
" this.waiting = false;\n", | |
"\n", | |
" this.ws.onopen = function () {\n", | |
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", | |
" fig.send_message(\"send_image_mode\", {});\n", | |
" if (mpl.ratio != 1) {\n", | |
" fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", | |
" }\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" }\n", | |
"\n", | |
" this.imageObj.onload = function() {\n", | |
" if (fig.image_mode == 'full') {\n", | |
" // Full images could contain transparency (where diff images\n", | |
" // almost always do), so we need to clear the canvas so that\n", | |
" // there is no ghosting.\n", | |
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", | |
" }\n", | |
" fig.context.drawImage(fig.imageObj, 0, 0);\n", | |
" };\n", | |
"\n", | |
" this.imageObj.onunload = function() {\n", | |
" fig.ws.close();\n", | |
" }\n", | |
"\n", | |
" this.ws.onmessage = this._make_on_message_function(this);\n", | |
"\n", | |
" this.ondownload = ondownload;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_header = function() {\n", | |
" var titlebar = $(\n", | |
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n", | |
" 'ui-helper-clearfix\"/>');\n", | |
" var titletext = $(\n", | |
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n", | |
" 'text-align: center; padding: 3px;\"/>');\n", | |
" titlebar.append(titletext)\n", | |
" this.root.append(titlebar);\n", | |
" this.header = titletext[0];\n", | |
"}\n", | |
"\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_canvas = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var canvas_div = $('<div/>');\n", | |
"\n", | |
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", | |
"\n", | |
" function canvas_keyboard_event(event) {\n", | |
" return fig.key_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" canvas_div.keydown('key_press', canvas_keyboard_event);\n", | |
" canvas_div.keyup('key_release', canvas_keyboard_event);\n", | |
" this.canvas_div = canvas_div\n", | |
" this._canvas_extra_style(canvas_div)\n", | |
" this.root.append(canvas_div);\n", | |
"\n", | |
" var canvas = $('<canvas/>');\n", | |
" canvas.addClass('mpl-canvas');\n", | |
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", | |
"\n", | |
" this.canvas = canvas[0];\n", | |
" this.context = canvas[0].getContext(\"2d\");\n", | |
"\n", | |
" var backingStore = this.context.backingStorePixelRatio ||\n", | |
"\tthis.context.webkitBackingStorePixelRatio ||\n", | |
"\tthis.context.mozBackingStorePixelRatio ||\n", | |
"\tthis.context.msBackingStorePixelRatio ||\n", | |
"\tthis.context.oBackingStorePixelRatio ||\n", | |
"\tthis.context.backingStorePixelRatio || 1;\n", | |
"\n", | |
" mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", | |
"\n", | |
" var rubberband = $('<canvas/>');\n", | |
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", | |
"\n", | |
" var pass_mouse_events = true;\n", | |
"\n", | |
" canvas_div.resizable({\n", | |
" start: function(event, ui) {\n", | |
" pass_mouse_events = false;\n", | |
" },\n", | |
" resize: function(event, ui) {\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" stop: function(event, ui) {\n", | |
" pass_mouse_events = true;\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" });\n", | |
"\n", | |
" function mouse_event_fn(event) {\n", | |
" if (pass_mouse_events)\n", | |
" return fig.mouse_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" rubberband.mousedown('button_press', mouse_event_fn);\n", | |
" rubberband.mouseup('button_release', mouse_event_fn);\n", | |
" // Throttle sequential mouse events to 1 every 20ms.\n", | |
" rubberband.mousemove('motion_notify', mouse_event_fn);\n", | |
"\n", | |
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n", | |
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n", | |
"\n", | |
" canvas_div.on(\"wheel\", function (event) {\n", | |
" event = event.originalEvent;\n", | |
" event['data'] = 'scroll'\n", | |
" if (event.deltaY < 0) {\n", | |
" event.step = 1;\n", | |
" } else {\n", | |
" event.step = -1;\n", | |
" }\n", | |
" mouse_event_fn(event);\n", | |
" });\n", | |
"\n", | |
" canvas_div.append(canvas);\n", | |
" canvas_div.append(rubberband);\n", | |
"\n", | |
" this.rubberband = rubberband;\n", | |
" this.rubberband_canvas = rubberband[0];\n", | |
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n", | |
" this.rubberband_context.strokeStyle = \"#000000\";\n", | |
"\n", | |
" this._resize_canvas = function(width, height) {\n", | |
" // Keep the size of the canvas, canvas container, and rubber band\n", | |
" // canvas in synch.\n", | |
" canvas_div.css('width', width)\n", | |
" canvas_div.css('height', height)\n", | |
"\n", | |
" canvas.attr('width', width * mpl.ratio);\n", | |
" canvas.attr('height', height * mpl.ratio);\n", | |
" canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", | |
"\n", | |
" rubberband.attr('width', width);\n", | |
" rubberband.attr('height', height);\n", | |
" }\n", | |
"\n", | |
" // Set the figure to an initial 600x600px, this will subsequently be updated\n", | |
" // upon first draw.\n", | |
" this._resize_canvas(600, 600);\n", | |
"\n", | |
" // Disable right mouse context menu.\n", | |
" $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", | |
" return false;\n", | |
" });\n", | |
"\n", | |
" function set_focus () {\n", | |
" canvas.focus();\n", | |
" canvas_div.focus();\n", | |
" }\n", | |
"\n", | |
" window.setTimeout(set_focus, 100);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_toolbar = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var nav_element = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items) {\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) {\n", | |
" // put a spacer in here.\n", | |
" continue;\n", | |
" }\n", | |
" var button = $('<button/>');\n", | |
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", | |
" 'ui-button-icon-only');\n", | |
" button.attr('role', 'button');\n", | |
" button.attr('aria-disabled', 'false');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
"\n", | |
" var icon_img = $('<span/>');\n", | |
" icon_img.addClass('ui-button-icon-primary ui-icon');\n", | |
" icon_img.addClass(image);\n", | |
" icon_img.addClass('ui-corner-all');\n", | |
"\n", | |
" var tooltip_span = $('<span/>');\n", | |
" tooltip_span.addClass('ui-button-text');\n", | |
" tooltip_span.html(tooltip);\n", | |
"\n", | |
" button.append(icon_img);\n", | |
" button.append(tooltip_span);\n", | |
"\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" var fmt_picker_span = $('<span/>');\n", | |
"\n", | |
" var fmt_picker = $('<select/>');\n", | |
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", | |
" fmt_picker_span.append(fmt_picker);\n", | |
" nav_element.append(fmt_picker_span);\n", | |
" this.format_dropdown = fmt_picker[0];\n", | |
"\n", | |
" for (var ind in mpl.extensions) {\n", | |
" var fmt = mpl.extensions[ind];\n", | |
" var option = $(\n", | |
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n", | |
" fmt_picker.append(option)\n", | |
" }\n", | |
"\n", | |
" // Add hover states to the ui-buttons\n", | |
" $( \".ui-button\" ).hover(\n", | |
" function() { $(this).addClass(\"ui-state-hover\");},\n", | |
" function() { $(this).removeClass(\"ui-state-hover\");}\n", | |
" );\n", | |
"\n", | |
" var status_bar = $('<span class=\"mpl-message\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n", | |
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", | |
" // which will in turn request a refresh of the image.\n", | |
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_message = function(type, properties) {\n", | |
" properties['type'] = type;\n", | |
" properties['figure_id'] = this.id;\n", | |
" this.ws.send(JSON.stringify(properties));\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_draw_message = function() {\n", | |
" if (!this.waiting) {\n", | |
" this.waiting = true;\n", | |
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" var format_dropdown = fig.format_dropdown;\n", | |
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", | |
" fig.ondownload(fig, format);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n", | |
" var size = msg['size'];\n", | |
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n", | |
" fig._resize_canvas(size[0], size[1]);\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n", | |
" var x0 = msg['x0'] / mpl.ratio;\n", | |
" var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n", | |
" var x1 = msg['x1'] / mpl.ratio;\n", | |
" var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n", | |
" x0 = Math.floor(x0) + 0.5;\n", | |
" y0 = Math.floor(y0) + 0.5;\n", | |
" x1 = Math.floor(x1) + 0.5;\n", | |
" y1 = Math.floor(y1) + 0.5;\n", | |
" var min_x = Math.min(x0, x1);\n", | |
" var min_y = Math.min(y0, y1);\n", | |
" var width = Math.abs(x1 - x0);\n", | |
" var height = Math.abs(y1 - y0);\n", | |
"\n", | |
" fig.rubberband_context.clearRect(\n", | |
" 0, 0, fig.canvas.width, fig.canvas.height);\n", | |
"\n", | |
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n", | |
" // Updates the figure title.\n", | |
" fig.header.textContent = msg['label'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n", | |
" var cursor = msg['cursor'];\n", | |
" switch(cursor)\n", | |
" {\n", | |
" case 0:\n", | |
" cursor = 'pointer';\n", | |
" break;\n", | |
" case 1:\n", | |
" cursor = 'default';\n", | |
" break;\n", | |
" case 2:\n", | |
" cursor = 'crosshair';\n", | |
" break;\n", | |
" case 3:\n", | |
" cursor = 'move';\n", | |
" break;\n", | |
" }\n", | |
" fig.rubberband_canvas.style.cursor = cursor;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_message = function(fig, msg) {\n", | |
" fig.message.textContent = msg['message'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n", | |
" // Request the server to send over a new figure.\n", | |
" fig.send_draw_message();\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n", | |
" fig.image_mode = msg['mode'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Called whenever the canvas gets updated.\n", | |
" this.send_message(\"ack\", {});\n", | |
"}\n", | |
"\n", | |
"// A function to construct a web socket function for onmessage handling.\n", | |
"// Called in the figure constructor.\n", | |
"mpl.figure.prototype._make_on_message_function = function(fig) {\n", | |
" return function socket_on_message(evt) {\n", | |
" if (evt.data instanceof Blob) {\n", | |
" /* FIXME: We get \"Resource interpreted as Image but\n", | |
" * transferred with MIME type text/plain:\" errors on\n", | |
" * Chrome. But how to set the MIME type? It doesn't seem\n", | |
" * to be part of the websocket stream */\n", | |
" evt.data.type = \"image/png\";\n", | |
"\n", | |
" /* Free the memory for the previous frames */\n", | |
" if (fig.imageObj.src) {\n", | |
" (window.URL || window.webkitURL).revokeObjectURL(\n", | |
" fig.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", | |
" evt.data);\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n", | |
" fig.imageObj.src = evt.data;\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var msg = JSON.parse(evt.data);\n", | |
" var msg_type = msg['type'];\n", | |
"\n", | |
" // Call the \"handle_{type}\" callback, which takes\n", | |
" // the figure and JSON message as its only arguments.\n", | |
" try {\n", | |
" var callback = fig[\"handle_\" + msg_type];\n", | |
" } catch (e) {\n", | |
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" if (callback) {\n", | |
" try {\n", | |
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", | |
" callback(fig, msg);\n", | |
" } catch (e) {\n", | |
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n", | |
" }\n", | |
" }\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", | |
"mpl.findpos = function(e) {\n", | |
" //this section is from http://www.quirksmode.org/js/events_properties.html\n", | |
" var targ;\n", | |
" if (!e)\n", | |
" e = window.event;\n", | |
" if (e.target)\n", | |
" targ = e.target;\n", | |
" else if (e.srcElement)\n", | |
" targ = e.srcElement;\n", | |
" if (targ.nodeType == 3) // defeat Safari bug\n", | |
" targ = targ.parentNode;\n", | |
"\n", | |
" // jQuery normalizes the pageX and pageY\n", | |
" // pageX,Y are the mouse positions relative to the document\n", | |
" // offset() returns the position of the element relative to the document\n", | |
" var x = e.pageX - $(targ).offset().left;\n", | |
" var y = e.pageY - $(targ).offset().top;\n", | |
"\n", | |
" return {\"x\": x, \"y\": y};\n", | |
"};\n", | |
"\n", | |
"/*\n", | |
" * return a copy of an object with only non-object keys\n", | |
" * we need this to avoid circular references\n", | |
" * http://stackoverflow.com/a/24161582/3208463\n", | |
" */\n", | |
"function simpleKeys (original) {\n", | |
" return Object.keys(original).reduce(function (obj, key) {\n", | |
" if (typeof original[key] !== 'object')\n", | |
" obj[key] = original[key]\n", | |
" return obj;\n", | |
" }, {});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.mouse_event = function(event, name) {\n", | |
" var canvas_pos = mpl.findpos(event)\n", | |
"\n", | |
" if (name === 'button_press')\n", | |
" {\n", | |
" this.canvas.focus();\n", | |
" this.canvas_div.focus();\n", | |
" }\n", | |
"\n", | |
" var x = canvas_pos.x * mpl.ratio;\n", | |
" var y = canvas_pos.y * mpl.ratio;\n", | |
"\n", | |
" this.send_message(name, {x: x, y: y, button: event.button,\n", | |
" step: event.step,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
"\n", | |
" /* This prevents the web browser from automatically changing to\n", | |
" * the text insertion cursor when the button is pressed. We want\n", | |
" * to control all of the cursor setting manually through the\n", | |
" * 'cursor' event from matplotlib */\n", | |
" event.preventDefault();\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" // Handle any extra behaviour associated with a key event\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.key_event = function(event, name) {\n", | |
"\n", | |
" // Prevent repeat events\n", | |
" if (name == 'key_press')\n", | |
" {\n", | |
" if (event.which === this._key)\n", | |
" return;\n", | |
" else\n", | |
" this._key = event.which;\n", | |
" }\n", | |
" if (name == 'key_release')\n", | |
" this._key = null;\n", | |
"\n", | |
" var value = '';\n", | |
" if (event.ctrlKey && event.which != 17)\n", | |
" value += \"ctrl+\";\n", | |
" if (event.altKey && event.which != 18)\n", | |
" value += \"alt+\";\n", | |
" if (event.shiftKey && event.which != 16)\n", | |
" value += \"shift+\";\n", | |
"\n", | |
" value += 'k';\n", | |
" value += event.which.toString();\n", | |
"\n", | |
" this._key_event_extra(event, name);\n", | |
"\n", | |
" this.send_message(name, {key: value,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n", | |
" if (name == 'download') {\n", | |
" this.handle_save(this, null);\n", | |
" } else {\n", | |
" this.send_message(\"toolbar_button\", {name: name});\n", | |
" }\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", | |
" this.message.textContent = tooltip;\n", | |
"};\n", | |
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", | |
"\n", | |
"mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", | |
"\n", | |
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n", | |
" // Create a \"websocket\"-like object which calls the given IPython comm\n", | |
" // object with the appropriate methods. Currently this is a non binary\n", | |
" // socket, so there is still some room for performance tuning.\n", | |
" var ws = {};\n", | |
"\n", | |
" ws.close = function() {\n", | |
" comm.close()\n", | |
" };\n", | |
" ws.send = function(m) {\n", | |
" //console.log('sending', m);\n", | |
" comm.send(m);\n", | |
" };\n", | |
" // Register the callback with on_msg.\n", | |
" comm.on_msg(function(msg) {\n", | |
" //console.log('receiving', msg['content']['data'], msg);\n", | |
" // Pass the mpl event to the overridden (by mpl) onmessage function.\n", | |
" ws.onmessage(msg['content']['data'])\n", | |
" });\n", | |
" return ws;\n", | |
"}\n", | |
"\n", | |
"mpl.mpl_figure_comm = function(comm, msg) {\n", | |
" // This is the function which gets called when the mpl process\n", | |
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n", | |
"\n", | |
" var id = msg.content.data.id;\n", | |
" // Get hold of the div created by the display call when the Comm\n", | |
" // socket was opened in Python.\n", | |
" var element = $(\"#\" + id);\n", | |
" var ws_proxy = comm_websocket_adapter(comm)\n", | |
"\n", | |
" function ondownload(figure, format) {\n", | |
" window.open(figure.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" var fig = new mpl.figure(id, ws_proxy,\n", | |
" ondownload,\n", | |
" element.get(0));\n", | |
"\n", | |
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", | |
" // web socket which is closed, not our websocket->open comm proxy.\n", | |
" ws_proxy.onopen();\n", | |
"\n", | |
" fig.parent_element = element.get(0);\n", | |
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n", | |
" if (!fig.cell_info) {\n", | |
" console.error(\"Failed to find cell for figure\", id, fig);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var output_index = fig.cell_info[2]\n", | |
" var cell = fig.cell_info[0];\n", | |
"\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.handle_close = function(fig, msg) {\n", | |
" var width = fig.canvas.width/mpl.ratio\n", | |
" fig.root.unbind('remove')\n", | |
"\n", | |
" // Update the output cell to use the data from the current canvas.\n", | |
" fig.push_to_output();\n", | |
" var dataURL = fig.canvas.toDataURL();\n", | |
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n", | |
" // the notebook keyboard shortcuts fail.\n", | |
" IPython.keyboard_manager.enable()\n", | |
" $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n", | |
" fig.close_ws(fig, msg);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.close_ws = function(fig, msg){\n", | |
" fig.send_message('closing', msg);\n", | |
" // fig.ws.close()\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", | |
" // Turn the data on the canvas into data in the output cell.\n", | |
" var width = this.canvas.width/mpl.ratio\n", | |
" var dataURL = this.canvas.toDataURL();\n", | |
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Tell IPython that the notebook contents must change.\n", | |
" IPython.notebook.set_dirty(true);\n", | |
" this.send_message(\"ack\", {});\n", | |
" var fig = this;\n", | |
" // Wait a second, then push the new image to the DOM so\n", | |
" // that it is saved nicely (might be nice to debounce this).\n", | |
" setTimeout(function () { fig.push_to_output() }, 1000);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_toolbar = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var nav_element = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items){\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) { continue; };\n", | |
"\n", | |
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" // Add the status bar.\n", | |
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"\n", | |
" // Add the close button to the window.\n", | |
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", | |
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", | |
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n", | |
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n", | |
" buttongrp.append(button);\n", | |
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", | |
" titlebar.prepend(buttongrp);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(el){\n", | |
" var fig = this\n", | |
" el.on(\"remove\", function(){\n", | |
"\tfig.close_ws(fig, {});\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(el){\n", | |
" // this is important to make the div 'focusable\n", | |
" el.attr('tabindex', 0)\n", | |
" // reach out to IPython and tell the keyboard manager to turn it's self\n", | |
" // off when our div gets focus\n", | |
"\n", | |
" // location in version 3\n", | |
" if (IPython.notebook.keyboard_manager) {\n", | |
" IPython.notebook.keyboard_manager.register_events(el);\n", | |
" }\n", | |
" else {\n", | |
" // location in version 2\n", | |
" IPython.keyboard_manager.register_events(el);\n", | |
" }\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" var manager = IPython.notebook.keyboard_manager;\n", | |
" if (!manager)\n", | |
" manager = IPython.keyboard_manager;\n", | |
"\n", | |
" // Check for shift+enter\n", | |
" if (event.shiftKey && event.which == 13) {\n", | |
" this.canvas_div.blur();\n", | |
" event.shiftKey = false;\n", | |
" // Send a \"J\" for go to next cell\n", | |
" event.which = 74;\n", | |
" event.keyCode = 74;\n", | |
" manager.command_mode();\n", | |
" manager.handle_keydown(event);\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" fig.ondownload(fig, null);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.find_output_cell = function(html_output) {\n", | |
" // Return the cell and output element which can be found *uniquely* in the notebook.\n", | |
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", | |
" // IPython event is triggered only after the cells have been serialised, which for\n", | |
" // our purposes (turning an active figure into a static one), is too late.\n", | |
" var cells = IPython.notebook.get_cells();\n", | |
" var ncells = cells.length;\n", | |
" for (var i=0; i<ncells; i++) {\n", | |
" var cell = cells[i];\n", | |
" if (cell.cell_type === 'code'){\n", | |
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n", | |
" var data = cell.output_area.outputs[j];\n", | |
" if (data.data) {\n", | |
" // IPython >= 3 moved mimebundle to data attribute of output\n", | |
" data = data.data;\n", | |
" }\n", | |
" if (data['text/html'] == html_output) {\n", | |
" return [cell, data, j];\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"// Register the function which deals with the matplotlib target/channel.\n", | |
"// The kernel may be null if the page has been refreshed.\n", | |
"if (IPython.notebook.kernel != null) {\n", | |
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", | |
"}\n" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/html": [ | |
"<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAgAElEQVR4Xuydd5wUxdaGX3JOy5LTkjMoOatIEgVBFBRFAVFBBUVR8RquVzF9qCiggIAiIqIgwYABJKcl5yBxAYlLziy7fL/qZYaZ2Zk9PVMzuz09b/9zL9Onqus8dfrsa1VXVYbr169fBy8SIAESIAESIAESIIGIIZCBAjBi+pqOkgAJkAAJkAAJkIBBgAKQgUACJEACJEACJEACEUaAAjDCOpzukgAJkAAJkAAJkAAFIGOABEiABEiABEiABCKMAAVghHU43SUBEiABEiABEiABCkDGAAmQAAmQAAmQAAlEGAEKwAjrcLpLAiRAAiRAAiRAAhSAjAESIAESIAESIAESiDACFIAR1uF0lwRIgARIgARIgAQoABkDJEACJEACJEACJBBhBCgAI6zD6S4JkAAJkAAJkAAJUAAyBkiABEiABEiABEggwghQAEZYh9NdEiABEiABEiABEqAAZAyQAAmQAAmQAAmQQIQRoACMsA6nuyRAAiRAAiRAAiRAAcgYIAESIAESIAESIIEII0ABGGEdTndJgARIgARIgARIgAKQMUACJEACJEACJEACEUaAAjDCOpzukgAJkAAJkAAJkAAFIGOABEiABEiABEiABCKMAAVghHU43SUBEiABEiABEiABCkDGAAmQAAmQAAmQAAlEGAEKwAjrcLpLAiRAAiRAAiRAAhSAjAESIAESIAESIAESiDACFIAR1uF0lwRIgARIgARIgAQoABkDJEACJEACJEACJBBhBCgAI6zD6S4JkAAJkAAJkAAJUAAyBkiABEiABEiABEggwghQAEZYh9NdEiABEiABEiABEqAAZAyQAAmQAAmQAAmQQIQRoACMsA6nuyRAAiRAAiRAAiRAAcgYIAESIAESIAESIIEII0ABGGEdTndJgARIgARIgARIgAKQMUACJEACJEACJEACEUaAAjDCOpzukgAJkAAJkAAJkAAFIGOABEiABEiABEiABCKMAAVghHU43SUBEiABEiABEiABCkDGAAmQAAmQAAmQAAlEGAEKwAjrcLpLAiRAAiRAAiRAAhSAjAESIAESIAESIAESiDACFIAR1uF0lwRIgARIgARIgAQoABkDJEACJEACJEACJBBhBCgAI6zD6S4JkAAJkAAJkAAJUAAyBkiA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\" width=\"640\">" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"#option_series=option_series[(option_series.index< '2009-01-01') & (option_series.index> '2008-09-01')]\n", | |
"#option_series=option_series[(option_series.index>'2016-01-01')]\n", | |
"ax = option_series.plot(logy=True)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 43, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:17:23.467631Z", | |
"start_time": "2018-10-06T17:17:23.426712Z" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"/* Put everything inside the global mpl namespace */\n", | |
"window.mpl = {};\n", | |
"\n", | |
"\n", | |
"mpl.get_websocket_type = function() {\n", | |
" if (typeof(WebSocket) !== 'undefined') {\n", | |
" return WebSocket;\n", | |
" } else if (typeof(MozWebSocket) !== 'undefined') {\n", | |
" return MozWebSocket;\n", | |
" } else {\n", | |
" alert('Your browser does not have WebSocket support.' +\n", | |
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", | |
" 'Firefox 4 and 5 are also supported but you ' +\n", | |
" 'have to enable WebSockets in about:config.');\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", | |
" this.id = figure_id;\n", | |
"\n", | |
" this.ws = websocket;\n", | |
"\n", | |
" this.supports_binary = (this.ws.binaryType != undefined);\n", | |
"\n", | |
" if (!this.supports_binary) {\n", | |
" var warnings = document.getElementById(\"mpl-warnings\");\n", | |
" if (warnings) {\n", | |
" warnings.style.display = 'block';\n", | |
" warnings.textContent = (\n", | |
" \"This browser does not support binary websocket messages. \" +\n", | |
" \"Performance may be slow.\");\n", | |
" }\n", | |
" }\n", | |
"\n", | |
" this.imageObj = new Image();\n", | |
"\n", | |
" this.context = undefined;\n", | |
" this.message = undefined;\n", | |
" this.canvas = undefined;\n", | |
" this.rubberband_canvas = undefined;\n", | |
" this.rubberband_context = undefined;\n", | |
" this.format_dropdown = undefined;\n", | |
"\n", | |
" this.image_mode = 'full';\n", | |
"\n", | |
" this.root = $('<div/>');\n", | |
" this._root_extra_style(this.root)\n", | |
" this.root.attr('style', 'display: inline-block');\n", | |
"\n", | |
" $(parent_element).append(this.root);\n", | |
"\n", | |
" this._init_header(this);\n", | |
" this._init_canvas(this);\n", | |
" this._init_toolbar(this);\n", | |
"\n", | |
" var fig = this;\n", | |
"\n", | |
" this.waiting = false;\n", | |
"\n", | |
" this.ws.onopen = function () {\n", | |
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", | |
" fig.send_message(\"send_image_mode\", {});\n", | |
" if (mpl.ratio != 1) {\n", | |
" fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", | |
" }\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" }\n", | |
"\n", | |
" this.imageObj.onload = function() {\n", | |
" if (fig.image_mode == 'full') {\n", | |
" // Full images could contain transparency (where diff images\n", | |
" // almost always do), so we need to clear the canvas so that\n", | |
" // there is no ghosting.\n", | |
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", | |
" }\n", | |
" fig.context.drawImage(fig.imageObj, 0, 0);\n", | |
" };\n", | |
"\n", | |
" this.imageObj.onunload = function() {\n", | |
" fig.ws.close();\n", | |
" }\n", | |
"\n", | |
" this.ws.onmessage = this._make_on_message_function(this);\n", | |
"\n", | |
" this.ondownload = ondownload;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_header = function() {\n", | |
" var titlebar = $(\n", | |
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n", | |
" 'ui-helper-clearfix\"/>');\n", | |
" var titletext = $(\n", | |
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n", | |
" 'text-align: center; padding: 3px;\"/>');\n", | |
" titlebar.append(titletext)\n", | |
" this.root.append(titlebar);\n", | |
" this.header = titletext[0];\n", | |
"}\n", | |
"\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_canvas = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var canvas_div = $('<div/>');\n", | |
"\n", | |
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", | |
"\n", | |
" function canvas_keyboard_event(event) {\n", | |
" return fig.key_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" canvas_div.keydown('key_press', canvas_keyboard_event);\n", | |
" canvas_div.keyup('key_release', canvas_keyboard_event);\n", | |
" this.canvas_div = canvas_div\n", | |
" this._canvas_extra_style(canvas_div)\n", | |
" this.root.append(canvas_div);\n", | |
"\n", | |
" var canvas = $('<canvas/>');\n", | |
" canvas.addClass('mpl-canvas');\n", | |
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", | |
"\n", | |
" this.canvas = canvas[0];\n", | |
" this.context = canvas[0].getContext(\"2d\");\n", | |
"\n", | |
" var backingStore = this.context.backingStorePixelRatio ||\n", | |
"\tthis.context.webkitBackingStorePixelRatio ||\n", | |
"\tthis.context.mozBackingStorePixelRatio ||\n", | |
"\tthis.context.msBackingStorePixelRatio ||\n", | |
"\tthis.context.oBackingStorePixelRatio ||\n", | |
"\tthis.context.backingStorePixelRatio || 1;\n", | |
"\n", | |
" mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", | |
"\n", | |
" var rubberband = $('<canvas/>');\n", | |
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", | |
"\n", | |
" var pass_mouse_events = true;\n", | |
"\n", | |
" canvas_div.resizable({\n", | |
" start: function(event, ui) {\n", | |
" pass_mouse_events = false;\n", | |
" },\n", | |
" resize: function(event, ui) {\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" stop: function(event, ui) {\n", | |
" pass_mouse_events = true;\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" });\n", | |
"\n", | |
" function mouse_event_fn(event) {\n", | |
" if (pass_mouse_events)\n", | |
" return fig.mouse_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" rubberband.mousedown('button_press', mouse_event_fn);\n", | |
" rubberband.mouseup('button_release', mouse_event_fn);\n", | |
" // Throttle sequential mouse events to 1 every 20ms.\n", | |
" rubberband.mousemove('motion_notify', mouse_event_fn);\n", | |
"\n", | |
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n", | |
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n", | |
"\n", | |
" canvas_div.on(\"wheel\", function (event) {\n", | |
" event = event.originalEvent;\n", | |
" event['data'] = 'scroll'\n", | |
" if (event.deltaY < 0) {\n", | |
" event.step = 1;\n", | |
" } else {\n", | |
" event.step = -1;\n", | |
" }\n", | |
" mouse_event_fn(event);\n", | |
" });\n", | |
"\n", | |
" canvas_div.append(canvas);\n", | |
" canvas_div.append(rubberband);\n", | |
"\n", | |
" this.rubberband = rubberband;\n", | |
" this.rubberband_canvas = rubberband[0];\n", | |
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n", | |
" this.rubberband_context.strokeStyle = \"#000000\";\n", | |
"\n", | |
" this._resize_canvas = function(width, height) {\n", | |
" // Keep the size of the canvas, canvas container, and rubber band\n", | |
" // canvas in synch.\n", | |
" canvas_div.css('width', width)\n", | |
" canvas_div.css('height', height)\n", | |
"\n", | |
" canvas.attr('width', width * mpl.ratio);\n", | |
" canvas.attr('height', height * mpl.ratio);\n", | |
" canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", | |
"\n", | |
" rubberband.attr('width', width);\n", | |
" rubberband.attr('height', height);\n", | |
" }\n", | |
"\n", | |
" // Set the figure to an initial 600x600px, this will subsequently be updated\n", | |
" // upon first draw.\n", | |
" this._resize_canvas(600, 600);\n", | |
"\n", | |
" // Disable right mouse context menu.\n", | |
" $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", | |
" return false;\n", | |
" });\n", | |
"\n", | |
" function set_focus () {\n", | |
" canvas.focus();\n", | |
" canvas_div.focus();\n", | |
" }\n", | |
"\n", | |
" window.setTimeout(set_focus, 100);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_toolbar = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var nav_element = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items) {\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) {\n", | |
" // put a spacer in here.\n", | |
" continue;\n", | |
" }\n", | |
" var button = $('<button/>');\n", | |
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", | |
" 'ui-button-icon-only');\n", | |
" button.attr('role', 'button');\n", | |
" button.attr('aria-disabled', 'false');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
"\n", | |
" var icon_img = $('<span/>');\n", | |
" icon_img.addClass('ui-button-icon-primary ui-icon');\n", | |
" icon_img.addClass(image);\n", | |
" icon_img.addClass('ui-corner-all');\n", | |
"\n", | |
" var tooltip_span = $('<span/>');\n", | |
" tooltip_span.addClass('ui-button-text');\n", | |
" tooltip_span.html(tooltip);\n", | |
"\n", | |
" button.append(icon_img);\n", | |
" button.append(tooltip_span);\n", | |
"\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" var fmt_picker_span = $('<span/>');\n", | |
"\n", | |
" var fmt_picker = $('<select/>');\n", | |
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", | |
" fmt_picker_span.append(fmt_picker);\n", | |
" nav_element.append(fmt_picker_span);\n", | |
" this.format_dropdown = fmt_picker[0];\n", | |
"\n", | |
" for (var ind in mpl.extensions) {\n", | |
" var fmt = mpl.extensions[ind];\n", | |
" var option = $(\n", | |
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n", | |
" fmt_picker.append(option)\n", | |
" }\n", | |
"\n", | |
" // Add hover states to the ui-buttons\n", | |
" $( \".ui-button\" ).hover(\n", | |
" function() { $(this).addClass(\"ui-state-hover\");},\n", | |
" function() { $(this).removeClass(\"ui-state-hover\");}\n", | |
" );\n", | |
"\n", | |
" var status_bar = $('<span class=\"mpl-message\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n", | |
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", | |
" // which will in turn request a refresh of the image.\n", | |
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_message = function(type, properties) {\n", | |
" properties['type'] = type;\n", | |
" properties['figure_id'] = this.id;\n", | |
" this.ws.send(JSON.stringify(properties));\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_draw_message = function() {\n", | |
" if (!this.waiting) {\n", | |
" this.waiting = true;\n", | |
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" var format_dropdown = fig.format_dropdown;\n", | |
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", | |
" fig.ondownload(fig, format);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n", | |
" var size = msg['size'];\n", | |
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n", | |
" fig._resize_canvas(size[0], size[1]);\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n", | |
" var x0 = msg['x0'] / mpl.ratio;\n", | |
" var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n", | |
" var x1 = msg['x1'] / mpl.ratio;\n", | |
" var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n", | |
" x0 = Math.floor(x0) + 0.5;\n", | |
" y0 = Math.floor(y0) + 0.5;\n", | |
" x1 = Math.floor(x1) + 0.5;\n", | |
" y1 = Math.floor(y1) + 0.5;\n", | |
" var min_x = Math.min(x0, x1);\n", | |
" var min_y = Math.min(y0, y1);\n", | |
" var width = Math.abs(x1 - x0);\n", | |
" var height = Math.abs(y1 - y0);\n", | |
"\n", | |
" fig.rubberband_context.clearRect(\n", | |
" 0, 0, fig.canvas.width, fig.canvas.height);\n", | |
"\n", | |
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n", | |
" // Updates the figure title.\n", | |
" fig.header.textContent = msg['label'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n", | |
" var cursor = msg['cursor'];\n", | |
" switch(cursor)\n", | |
" {\n", | |
" case 0:\n", | |
" cursor = 'pointer';\n", | |
" break;\n", | |
" case 1:\n", | |
" cursor = 'default';\n", | |
" break;\n", | |
" case 2:\n", | |
" cursor = 'crosshair';\n", | |
" break;\n", | |
" case 3:\n", | |
" cursor = 'move';\n", | |
" break;\n", | |
" }\n", | |
" fig.rubberband_canvas.style.cursor = cursor;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_message = function(fig, msg) {\n", | |
" fig.message.textContent = msg['message'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n", | |
" // Request the server to send over a new figure.\n", | |
" fig.send_draw_message();\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n", | |
" fig.image_mode = msg['mode'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Called whenever the canvas gets updated.\n", | |
" this.send_message(\"ack\", {});\n", | |
"}\n", | |
"\n", | |
"// A function to construct a web socket function for onmessage handling.\n", | |
"// Called in the figure constructor.\n", | |
"mpl.figure.prototype._make_on_message_function = function(fig) {\n", | |
" return function socket_on_message(evt) {\n", | |
" if (evt.data instanceof Blob) {\n", | |
" /* FIXME: We get \"Resource interpreted as Image but\n", | |
" * transferred with MIME type text/plain:\" errors on\n", | |
" * Chrome. But how to set the MIME type? It doesn't seem\n", | |
" * to be part of the websocket stream */\n", | |
" evt.data.type = \"image/png\";\n", | |
"\n", | |
" /* Free the memory for the previous frames */\n", | |
" if (fig.imageObj.src) {\n", | |
" (window.URL || window.webkitURL).revokeObjectURL(\n", | |
" fig.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", | |
" evt.data);\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n", | |
" fig.imageObj.src = evt.data;\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var msg = JSON.parse(evt.data);\n", | |
" var msg_type = msg['type'];\n", | |
"\n", | |
" // Call the \"handle_{type}\" callback, which takes\n", | |
" // the figure and JSON message as its only arguments.\n", | |
" try {\n", | |
" var callback = fig[\"handle_\" + msg_type];\n", | |
" } catch (e) {\n", | |
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" if (callback) {\n", | |
" try {\n", | |
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", | |
" callback(fig, msg);\n", | |
" } catch (e) {\n", | |
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n", | |
" }\n", | |
" }\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", | |
"mpl.findpos = function(e) {\n", | |
" //this section is from http://www.quirksmode.org/js/events_properties.html\n", | |
" var targ;\n", | |
" if (!e)\n", | |
" e = window.event;\n", | |
" if (e.target)\n", | |
" targ = e.target;\n", | |
" else if (e.srcElement)\n", | |
" targ = e.srcElement;\n", | |
" if (targ.nodeType == 3) // defeat Safari bug\n", | |
" targ = targ.parentNode;\n", | |
"\n", | |
" // jQuery normalizes the pageX and pageY\n", | |
" // pageX,Y are the mouse positions relative to the document\n", | |
" // offset() returns the position of the element relative to the document\n", | |
" var x = e.pageX - $(targ).offset().left;\n", | |
" var y = e.pageY - $(targ).offset().top;\n", | |
"\n", | |
" return {\"x\": x, \"y\": y};\n", | |
"};\n", | |
"\n", | |
"/*\n", | |
" * return a copy of an object with only non-object keys\n", | |
" * we need this to avoid circular references\n", | |
" * http://stackoverflow.com/a/24161582/3208463\n", | |
" */\n", | |
"function simpleKeys (original) {\n", | |
" return Object.keys(original).reduce(function (obj, key) {\n", | |
" if (typeof original[key] !== 'object')\n", | |
" obj[key] = original[key]\n", | |
" return obj;\n", | |
" }, {});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.mouse_event = function(event, name) {\n", | |
" var canvas_pos = mpl.findpos(event)\n", | |
"\n", | |
" if (name === 'button_press')\n", | |
" {\n", | |
" this.canvas.focus();\n", | |
" this.canvas_div.focus();\n", | |
" }\n", | |
"\n", | |
" var x = canvas_pos.x * mpl.ratio;\n", | |
" var y = canvas_pos.y * mpl.ratio;\n", | |
"\n", | |
" this.send_message(name, {x: x, y: y, button: event.button,\n", | |
" step: event.step,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
"\n", | |
" /* This prevents the web browser from automatically changing to\n", | |
" * the text insertion cursor when the button is pressed. We want\n", | |
" * to control all of the cursor setting manually through the\n", | |
" * 'cursor' event from matplotlib */\n", | |
" event.preventDefault();\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" // Handle any extra behaviour associated with a key event\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.key_event = function(event, name) {\n", | |
"\n", | |
" // Prevent repeat events\n", | |
" if (name == 'key_press')\n", | |
" {\n", | |
" if (event.which === this._key)\n", | |
" return;\n", | |
" else\n", | |
" this._key = event.which;\n", | |
" }\n", | |
" if (name == 'key_release')\n", | |
" this._key = null;\n", | |
"\n", | |
" var value = '';\n", | |
" if (event.ctrlKey && event.which != 17)\n", | |
" value += \"ctrl+\";\n", | |
" if (event.altKey && event.which != 18)\n", | |
" value += \"alt+\";\n", | |
" if (event.shiftKey && event.which != 16)\n", | |
" value += \"shift+\";\n", | |
"\n", | |
" value += 'k';\n", | |
" value += event.which.toString();\n", | |
"\n", | |
" this._key_event_extra(event, name);\n", | |
"\n", | |
" this.send_message(name, {key: value,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n", | |
" if (name == 'download') {\n", | |
" this.handle_save(this, null);\n", | |
" } else {\n", | |
" this.send_message(\"toolbar_button\", {name: name});\n", | |
" }\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", | |
" this.message.textContent = tooltip;\n", | |
"};\n", | |
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", | |
"\n", | |
"mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", | |
"\n", | |
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n", | |
" // Create a \"websocket\"-like object which calls the given IPython comm\n", | |
" // object with the appropriate methods. Currently this is a non binary\n", | |
" // socket, so there is still some room for performance tuning.\n", | |
" var ws = {};\n", | |
"\n", | |
" ws.close = function() {\n", | |
" comm.close()\n", | |
" };\n", | |
" ws.send = function(m) {\n", | |
" //console.log('sending', m);\n", | |
" comm.send(m);\n", | |
" };\n", | |
" // Register the callback with on_msg.\n", | |
" comm.on_msg(function(msg) {\n", | |
" //console.log('receiving', msg['content']['data'], msg);\n", | |
" // Pass the mpl event to the overridden (by mpl) onmessage function.\n", | |
" ws.onmessage(msg['content']['data'])\n", | |
" });\n", | |
" return ws;\n", | |
"}\n", | |
"\n", | |
"mpl.mpl_figure_comm = function(comm, msg) {\n", | |
" // This is the function which gets called when the mpl process\n", | |
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n", | |
"\n", | |
" var id = msg.content.data.id;\n", | |
" // Get hold of the div created by the display call when the Comm\n", | |
" // socket was opened in Python.\n", | |
" var element = $(\"#\" + id);\n", | |
" var ws_proxy = comm_websocket_adapter(comm)\n", | |
"\n", | |
" function ondownload(figure, format) {\n", | |
" window.open(figure.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" var fig = new mpl.figure(id, ws_proxy,\n", | |
" ondownload,\n", | |
" element.get(0));\n", | |
"\n", | |
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", | |
" // web socket which is closed, not our websocket->open comm proxy.\n", | |
" ws_proxy.onopen();\n", | |
"\n", | |
" fig.parent_element = element.get(0);\n", | |
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n", | |
" if (!fig.cell_info) {\n", | |
" console.error(\"Failed to find cell for figure\", id, fig);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var output_index = fig.cell_info[2]\n", | |
" var cell = fig.cell_info[0];\n", | |
"\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.handle_close = function(fig, msg) {\n", | |
" var width = fig.canvas.width/mpl.ratio\n", | |
" fig.root.unbind('remove')\n", | |
"\n", | |
" // Update the output cell to use the data from the current canvas.\n", | |
" fig.push_to_output();\n", | |
" var dataURL = fig.canvas.toDataURL();\n", | |
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n", | |
" // the notebook keyboard shortcuts fail.\n", | |
" IPython.keyboard_manager.enable()\n", | |
" $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n", | |
" fig.close_ws(fig, msg);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.close_ws = function(fig, msg){\n", | |
" fig.send_message('closing', msg);\n", | |
" // fig.ws.close()\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", | |
" // Turn the data on the canvas into data in the output cell.\n", | |
" var width = this.canvas.width/mpl.ratio\n", | |
" var dataURL = this.canvas.toDataURL();\n", | |
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Tell IPython that the notebook contents must change.\n", | |
" IPython.notebook.set_dirty(true);\n", | |
" this.send_message(\"ack\", {});\n", | |
" var fig = this;\n", | |
" // Wait a second, then push the new image to the DOM so\n", | |
" // that it is saved nicely (might be nice to debounce this).\n", | |
" setTimeout(function () { fig.push_to_output() }, 1000);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_toolbar = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var nav_element = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items){\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) { continue; };\n", | |
"\n", | |
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" // Add the status bar.\n", | |
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"\n", | |
" // Add the close button to the window.\n", | |
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", | |
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", | |
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n", | |
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n", | |
" buttongrp.append(button);\n", | |
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", | |
" titlebar.prepend(buttongrp);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(el){\n", | |
" var fig = this\n", | |
" el.on(\"remove\", function(){\n", | |
"\tfig.close_ws(fig, {});\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(el){\n", | |
" // this is important to make the div 'focusable\n", | |
" el.attr('tabindex', 0)\n", | |
" // reach out to IPython and tell the keyboard manager to turn it's self\n", | |
" // off when our div gets focus\n", | |
"\n", | |
" // location in version 3\n", | |
" if (IPython.notebook.keyboard_manager) {\n", | |
" IPython.notebook.keyboard_manager.register_events(el);\n", | |
" }\n", | |
" else {\n", | |
" // location in version 2\n", | |
" IPython.keyboard_manager.register_events(el);\n", | |
" }\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" var manager = IPython.notebook.keyboard_manager;\n", | |
" if (!manager)\n", | |
" manager = IPython.keyboard_manager;\n", | |
"\n", | |
" // Check for shift+enter\n", | |
" if (event.shiftKey && event.which == 13) {\n", | |
" this.canvas_div.blur();\n", | |
" event.shiftKey = false;\n", | |
" // Send a \"J\" for go to next cell\n", | |
" event.which = 74;\n", | |
" event.keyCode = 74;\n", | |
" manager.command_mode();\n", | |
" manager.handle_keydown(event);\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" fig.ondownload(fig, null);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.find_output_cell = function(html_output) {\n", | |
" // Return the cell and output element which can be found *uniquely* in the notebook.\n", | |
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", | |
" // IPython event is triggered only after the cells have been serialised, which for\n", | |
" // our purposes (turning an active figure into a static one), is too late.\n", | |
" var cells = IPython.notebook.get_cells();\n", | |
" var ncells = cells.length;\n", | |
" for (var i=0; i<ncells; i++) {\n", | |
" var cell = cells[i];\n", | |
" if (cell.cell_type === 'code'){\n", | |
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n", | |
" var data = cell.output_area.outputs[j];\n", | |
" if (data.data) {\n", | |
" // IPython >= 3 moved mimebundle to data attribute of output\n", | |
" data = data.data;\n", | |
" }\n", | |
" if (data['text/html'] == html_output) {\n", | |
" return [cell, data, j];\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"// Register the function which deals with the matplotlib target/channel.\n", | |
"// The kernel may be null if the page has been refreshed.\n", | |
"if (IPython.notebook.kernel != null) {\n", | |
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", | |
"}\n" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/html": [ | |
"<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAgAElEQVR4Xu2dC7iWc7r/7+QUmkGNYWxt7IzDHpoUZWvLqfbGVoQcktMOkbNSDm3T5FA0lIgOZJeMS0gaDOUwmMupHMcwtrFN9rUTxWaIS9L/+j3+a+mwjNV9r7vW73d/3uva19Ba97Pe9/P9rnt/et7neTVZunTpUuEBAQhAAAIQgAAEIBCGQBMEMEzWvFAIQAACEIAABCBQEUAAKQIEIAABCEAAAhAIRgABDBY4LxcCEIAABCAAAQgggHQAAhCAAAQgAAEIBCOAAAYLnJcLAQhAAAIQgAAEEEA6AAEIQAACEIAABIIRQACDBc7LhQAEIAABCEAAAgggHYAABCAAAQhAAALBCCCAwQLn5UIAAhCAAAQgAAEEkA5AAAIQgAAEIACBYAQQwGCB83IhAAEIQAACEIAAAkgHIAABCEAAAhCAQDACCGCwwHm5EIAABCAAAQhAAAGkAxCAAAQgAAEIQCAYAQQwWOC8XAhAAAIQgAAEIIAA0gEIQAACEIAABCAQjAACGCxwXi4EIAABCEAAAhBAAOkABCAAAQhAAAIQCEYAAQwWOC8XAhCAAAQgAAEIIIB0AAIQgAAEIAABCAQjgAAGC5yXCwEIQAACEIAABBBAOgABCEAAAhCAAASCEUAAgwXOy4UABCAAAQhAAAIIIB2AAAQgAAEIQAACwQgggMEC5+VCAAIQgAAEIAABBJAOQAACEIAABCAAgWAEEMBggfNyIQABCEAAAhCAAAJIByAAAQhAAAIQgEAwAghgsMB5uRCAAAQgAAEIQAABpAMQgAAEIAABCEAgGAEEMFjgvFwIQAACEIAABCCAANIBCEAAAhCAAAQgEIwAAhgscF4uBCAAAQhAAAIQQADpAAQgAAEIQAACEAhGAAEMFjgvFwIQgAAEIAABCCCAdAACEICAiCxdulSaNGkCCwhAAAIhCCCAIWLmRUKgPAJz5syRW2+9VV544QX55JNPZLPNNpM99thDTjzxRPmHf/iHVXrB6Vhjx46VcePGVXP/8z//I/vtt59ceeWV0qNHj1U6Ft8MAQhAIAcCCGAOKfEcIQCB5QgkUbvmmmtkzz33lEMPPbSSv7/85S/y61//Wt56661K3A466KB6Uxs0aJA899xz8uijj1YzX375pfzxj3+UVq1ayaabblrv4/CNEIAABHIhgADmkhTPEwIQqAg89thj0rdvXzn99NPl7LPPXo7K4sWL5fzzz6++55577pHtttuuXtRWFMB6DfFNEIAABDImgABmHB5PHQIRCRx22GHy2WefyYMPPljnNXsfffSR7LPPPtK1a1e56qqrZPvtt5fBgwfLq6++Kg8//LA0a9ZMDjzwQOnfv7+sv/76kuRv2rRptSjT2cPdd999pbeA33nnneqsY3q7OP38nXfeWc455xxp165dNVvztvHIkSOr5/bkk0/K2muvXT2Piy66SDbccMPq+1577bXqef3hD3+Qr7/+Wtq0aSPnnntu9b88IAABCKwuAgjg6iLNz4EABMwEPvzww+o6v5NOOkkGDhz4ncdLZwefffbZStaSAP7gBz+oBKt3797y5z//WZKkde7cWUaPHi1z586Vyy67rHrL9/rrr6/e9l20aNFyApjeVu7Zs6f8/d//vZxyyimyzjrryKRJk6rrD2+55ZZKGGsE8Ic//KEkSd1rr73klVdekWuvvVZOPvnk6szkp59+Kl26dJEOHTrIEUccIemM5Y033lg9p3TWsnnz5mZGHAACEIBAfQgggPWhxPdAAAKNgkA6i3f44YfLf/zHf0ivXr2+8zkNHz68ErN0XV+Ss6233lruv//+6oxceqSbR9KZvt/85jfV28QrvgW84k0g6Uzf008/LbNmzaqVtK+++kr+7d/+rfr3qVOn1gpgt27d5Oqrr659bscdd5yks5IzZsyQl156SY488ki5/fbba88cJgG94447KjndYostGgVnngQEIFA+AQSw/Ix5hRAohkA6o5bOnA0dOrQ6I/ddjxEjRsj48eOrs4DpbFu/fv3krLPOqv32efPmyd577y2/+MUv5Oijj/5eAfynf/qn6ozesGHDlvuR6QziDTfcUJ1pTJKX7hxeUU4vuOCC6uuPPPJI9dbx/vvvL0uWLJEDDjigOguZzmimt6V5QAACEFidBBDA1UmbnwUBCJgILFy4UJKMpZtA0nVz3/VIN4c88cQT8uKLL1ZvAQ8ZMkSOOuqo2m9Pd/mma/jOO+88OfXUU79XAP/xH/+x+niZdN3gso9013GSyPSz0tu5dX10zIpnF99+++3qbd/HH3+8+viaJH/prOHFF18s6623nokPwxCAAATqSwABrC8pvg8CEGgUBNJbqEmcHnjg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9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKAGYqgG+88YYMHz5cXnvtNVlnnXVkzz33lEGDBsmmm24ql156qdx9993Vn9c80teOPPLI6l/Hjx8vkydPlk8++UR23nlnGTJkiGy77bbV1xYtWiRDhw6VRx99VL766ivZb7/9quNtuOGGdbYWAfT5ZS7xqJoFVRIHBDCvNKP31SstuPqQ1XBFADMUwC+++EL2339/6dmzp/Tt21c+++wzGThwoKy11lpy0003SY8ePaR3795y6KGHrtS0adOmybXXXis333yztGrVqvrnp556SmbMmCFNmjSRCy+8UObNmycjR46UJUuWyDnnnCOtW7euJLCuBwLo88tc4lE1C6okDghgXmlG76tXWnD1IavhigBmKIBvv/22XHHFFTJ27Fhp2rRp1aZHHnlELrjgAnn66adl1113lSR622233UpNO/roo6Vz586VOKbH4sWLpUOHDjJmzBhp06aN7LbbbjJp0qTqGOnx8ssvy3HHHSfPPPOMNGvWbKXjIYA+v8wlHlWzoErigADmlWb0vnqlBVcfshquCGCGAlhXfZL8vffee9K/f//qzGCXLl1kzpw50rx5cznssMOkT58+1RnCJHjpreN999239jDpjGG3bt2kY8eO0r1792puo402qr7+6aefSrt27eTee++VHXfcEQH0+d0NcVTNgioJDAKYV5rR++qVFlx9yGq4IoCZC2B6+unt2ttvv11uu+02WbBgQXVm8IwzzpC2bdvK66+/Lv369ZPjjz++ksCddtqpevt3jz32qG3hMcccI506dZLdd99devXqVc0kWUyP9DZwmpkyZYq0b9++TgFMxSvpkV5PixbNZeHCv8rSpSW9sjX7WqJzbT/iiTUbgOKnz+6/l2KqjJHoffVKEa4+ZDVcW7Zs7vNkMjlqk6UZC2A6O5eu2Us3gtx4442y/fbb14l9woQJ8sADD8g999xTnc0bMWKE7LPPPsudAUxn/tLZwXTd4AsvvFB700fNGcDp06fLDjvssNLxlyz5Wpo2/UYWeUAAAt9NYOtB92eH551hB2X3nHnCEIAABOpDIFsBnDt3rpx88snyk5/8RH71q19Vd/+mx6xZs6qzgEcddVTt60/X96UbPdJZwvTn6e3fU045pfp6zTWAN9xwg/z85z+vJDCd7UvXA6ZHugYwnRWcPXu2rL/++isxTdcAcgawPlXjezR/Qy2JGmcA80ozel+90oKrD1kNV84AZngG8OOPP5ZDDjmkumbv8ssvr327NtVq5syZ1XWA6W7g9PWXXnpJTjvttOpMYTrLN3XqVBk9erSMGzdOttlmm+ou4PSRL/fff3/1sTEDBgyoriUcNWpU1dKzzz5bttxySxk2bFidreUmEJ9f5hKPqrlGpSQOXAOYV5rR++qVFlx9yGq4cg1ghgI4ceLESsjSXbnpo1uWfbz44otyxx13SPqe+fPnS8uWLeXEE0+szuKlR3q56WvpLN+HH35Y+zmASQbTI73lm24SSVKYzg6mzwEcPHiwbLDBBgigz+9tmKNqFlRJcBDAvNKM3levtODqQ1bDFQHMUAB96qM7KmcAddwiTmkWVEmcEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1r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662yyy67yLPPPlsJ4fjx46t/nzJlitx0003y2GOPSbNmzeT666+Xhx9+WMaOHSvNmzev5DAdf9y4cQigz+9tmKNqFlRJcBDAvNKM3levtODqQ1bDFQHMUADffvttueKKKypJa9q0adWmRx55RC644ILqLOCECRPkoYceqm3ZpZdeKkkakxz279+/Er2hQ4fWfv2AAw6QPn36yGGHHSadO3euvufggw+uvr5gwQLp1KmTzJw5U7baaquVmssZQJ9f5hKPqllQJXFAAPNKM3pfvdKCqw9ZDVcEMEMBrKs+Sf7ee+892WGHHWTevHkyevTo2m+bPHmy3HXXXdXbuoccckgler179679+plnnimbb755ddawffv2ct9998n2229f+/UOHTrI5ZdfXp11XPGBAPr8Mpd4VM2CKokDAphXmtH76pUWXH3IargigJkLYHr6I0eOlNtvv11uu+02mTRpkixevFiuuuqq2pZNnTq1egs3ncXr0qWLnHrqqXL44YfXfn3AgAGy7rrrShLBdAZw1qxZy53tS3923nnnSffu3esUwFS8kh7p9bRo0VwWLvyrLF1a0itbs68lOtf2I55YswEofvrs/nsppsoYid5XrxTh6kNWw7Vly+Y+TyaTozZZmrEAfvrpp3LhhRdWN4LceOON1Vm7dPPH+++/L9ddd91yZwDvvvtuuffee6Vbt27VtYPHHnvscmcAt9hii+pawd13311mzJghP/3pT+t1BnDJkq+ladO1MombpwmBNUdg60H3r7kfrvzJ7ww7SDnJGAQgAIHGTSBbAZw7d66cfPLJ8pOf/ER+9atfVXf/psedd94pEydOlAcffLCWfLoGcNGiRXL11VfL+eefLxtttFF1Z2/NI10DeNJJJ1V3Cu+1117VdYQHHnhg9eV0p3DNNYCtWrVaKc30FjBnABt3yRvLs9P8DbWxPPeGeB6cAWwIiqvvGNH76kUarj5kNVw5A5jhGcCPP/64upYvfURLujYv3f1b8/joo4+qu4DT2bxevXrJnDlz5PTTT68+9iV9/9NPP119Lf17u3btqruA0z+nO3833njj6u3kdENJ+rP0ETLpLuB0I0i6jrCuB9cA+vwyl3hUzTUqJXHgGsC80ozeV6+04OpDVsOVawAzFMB0hm/YsGHV3bxNVjj99uKLL8qrr75aieGbb75ZnRlMAtijR4/a1qWbQdJbxvPnz5fWrVvLJZdcIm3atKm+nq4fHDVqVHUjSPr4l3QDSLpjuEWLFgigz+9tmKNqFlRJcBDAvNKM3levtODqQ1bDFQHMUAB96qM7KmcAddwiTmkWVEmcEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtCLyYTsAACAASURBVODqQ1bDFQFEAE1tRABN+EINaxZUSYAQwLzSjN5Xr7Tg6kNWwxUBRABNbUQATfhCDWsWVEmAEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtODqQ1bDFQFEAE1tRABN+EINaxZUSYAQwLzSjN5Xr7Tg6kNWwxUBRABNbUQATfhCDWsWVEmAEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtODqQ1bDFQFEAE1tRABN+EINaxZUSYAQwLzSjN5Xr7Tg6kNWwxUBRABNbUQATfhCDWsWVEmAEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtODqQ1bDFQFEAE1tRABN+EINaxZUSYAQwLzSjN5Xr7Tg6kNWwxUBRABNbUQATfhCDWsWVEmAEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtODqQ1bDFQFEAE1tRABN+EINaxZUSYAQwLzSjN5Xr7Tg6kNWwxUBRABNbUQATfhCDWsWVEmAEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtODqQ1bDFQFEAE1tRABN+EINaxZUSYAQwLzSjN5Xr7Tg6kNWwxUBRABNbUQATfhCDWsWVEmAEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtODqQ1bDFQFEAE1tRABN+EINaxZUSYAQwLzSjN5Xr7Tg6kNWwxUBRABNbUQATfhCDWsWVEmAEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtODqQ1bDFQFEAE1tRABN+EINaxZUSYAQwLzSjN5Xr7Tg6kNWwxUBRABNbUQATfhCDWsWVEmAEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtODqQ1bDFQFEAE1tRABN+EINaxZUSYAQwLzSjN5Xr7Tg6kNWwxUBRABNbUQATfhCDWsWVEmAEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtODqQ1bDFQFEAE1tRABN+EINaxZUSYAQwLzSjN5Xr7Tg6kNWwxUBRABNbUQATfhCDWsWVEmAEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtODqQ1bDFQFEAE1tRABN+EINaxZUSYAQwLzSjN5Xr7Tg6kNWwxUBRABNbUQATfhCDWsWVEmAEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtODqQ1bDFQFEAE1tRABN+EINaxZUSYAQwLzSjN5Xr7Tg6kNWwxUBRABNbUQATfhCDWsWVEmAEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtODqQ1bDFQFEAE1tRABN+EINaxZUSYAQwLzSjN5Xr7Tg6kNWwxUBRABNbUQATfhCDWsWVEmAEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtODqQ1bDFQFEAE1tRABN+EINaxZUSYAQwLzSjN5Xr7Tg6kNWwxUBRABNbUQATfhCDWsWVEmAEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtODqQ1bDFQFEAE1tRABN+EINaxZUSYAQwLzSjN5Xr7Tg6kNWwxUBRABNbUQATfhCDWsWVEmAEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtODqQ1bDFQFEAE1tRABN+EINaxZUSYAQwLzSjN5Xr7Tg6kNWwxUBRABNbUQATfhCDWsWVEmAEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtODqQ1bDFQFEAE1tRABN+EINaxZUSYAQwLzSjN5Xr7Tg6kNWwxUBRABNbUQATfhCDWsWVEmAEMC80ozeV6+04OpDVsMVAUQATW1EAE34Qg1rFlRJgBDAvNKM3levtODqQ1bDFQHMXAA//PBDOfLII+Wyyy6TDh06VM269NJL5e6775Z11lmntmmDBg2qvi89xo8fL5MnT5ZPPvlEdt55ZxkyZIhsu+221dcWLVokQ4cOlUcffVS++uor2W+//arjbbjhhnW2FgH0+WUu8aiaBVUSBwQwrzSj99UrLbj6kNVwRQAzFsA5c+ZIEru5c+fKpEmTagWwR48e0rt3bzn00ENXatq0adPk2muvlZtvvllatWpV/fNTTz0lM2bMkCZNmsiFF14o8+bNk5EjR8qSJUvknHPOkdatW1cSWNcDAfT5ZS7xqJoFVRIHBDCvNKP31SstuPqQ1XBFADMVwCRy1113nQwYMEDOPffcWgH88ssvZdddd5X09e22226lph199NHSuXNn6du3b/W1xYsXV+I4ZswYadOmjey2227VsdIx0uPll1+W4447Tp555hlp1qzZSsdDAH1+mUs8qmZBlcQBAcwrzeh99UoLrj5kNVwRwEwF8IMPPpBNNtlE1l57bdl+++1rBfCVV16Rnj17SpcuXSSdIWzevLkcdthh0qdPH1lrrbUqwRs+fLjsu+++tS1MZwy7desmHTt2lO7du1dzG220UfX1Tz/9VNq1ayf33nuv7Ljjjgigz+9uiKNqFlRJYBDAvNKM3levtODqQ1bDFQHMVACXrdCyAvj73/9exo4dK2eccYa0bdtWXn/9denXr58cf/zxlQTutNNO1du/e+yxR+0hjjnmGOnUqZPsvvvu0qtXr2omyWJ6pLeB08yUKVOkffv2dQpgKl5Jj/R6WrRoLgsX/lWWLi3pla3Z1xKda/sRT6zZABQ/fXb/vRRTZYxE76tXinD1Iavh2rJlc58nk8lRmywtTADr4j5hwgR54IEH5J577qnO5o0YMUL22Wef5c4ApjN/6exgum7whRdeqL3po+YM4PTp02WHHXZY6fBLlnwtTZt+I4s8IACB7yaw9aD7s8PzzrCDsnvOPGEIQAAC9SFQnADOmjVLFixYIEcddVTt60/X96UbPW6//fbqz9Pbv6ecckr19ZprAG+44Qb5+c9/XklgOtuXrgdMj3QNYDorOHv2bFl//fVXYpquAeQMYH2qxvdo/oZaEjXOAOaVZvS+eqUFVx+yGq6cASzsDODMmTOlf//+ctNNN1XX9L300kty2mmnVXf3prN8U6dOldGjR8u4ceNkm222qe4CTh/5cv/991cfG5NuKnnvvfdk1KhRVUvPPvts2XLLLWXYsGF1tpabQHx+mUs8quYalZI4cA1gXmlG76tXWnD1IavhyjWAhQlgqtYdd9whEydOlPnz50vLli3lxBNPrM7ipUd6uelr6Sxf+gzBms8BTDKYHukt33STSJLCdHYwfQ7g4MGDZYMNNkAAfX5vwxxVs6BKgoMA5pVm9L56pQVXH7IarghgAQLoU6f6HZUzgPXjxHdJdalAesthwYKYN9cggHn9FkTvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigAigKY2IoAmfKGGNQuqJEAIYF5pRu+rV1pw9SGr4YoAIoCmNiKAJnyhhjULqiRACGBeaUbvq1dacPUhq+GKACKApjYigCZ8oYY1C6okQAhgXmlG76tXWnD1IavhigBmLoAffvihHHnkkXLZZZdJhw4dqma9/PLL1b+/9dZbsskmm8hpp50mRxxxRG3rpk2bJmPGjJEPPvhAtt12Wxk8eLC0bdu2+vqSJUtkxIgRMn36dPn888+lY8eOMmTIENlss83qbC0C6PPLXOJRNQuqJA4IYF5pRu+rV1pw9SGr4YoAZiyAc+bMkUGDBsncuXNl0qRJlQB+/PHH0rVrVznrrLMqMXz++eelX79+cuutt8ouu+wizz77bCWE48ePr/59ypQpctNNN8ljjz0mzZo1k+uvv14efvhhGTt2rDRv3rySw88++0zGjRuHAPr83oY5qmZBlQQHAcwrzeh99UoLrj5kNVwRwEwFMJ3Fu+6662TAgAFy7rnn1grg1KlTZcKECfLQQw/VtuzSSy+VL774QoYPHy79+/evRG/o0KG1Xz/ggAOkT58+cthhh0nnzp2r7zn44IOrry9YsEA6deokM2fOlK222mql5nIG0OeXucSjahZUSRwQwLzSjN5Xr7Tg6kNWwxUBzFQA09u36e3dtddeW7bffvtaAbziiitk3rx5Mnr06NqWTZ48We66667qbd1DDjmkEr3evXvXfv3MM8+UzTffvDpr2L59e7nvvvuqY9Y80pnFyy+/XPbff38E0Od3N8RRNQuqJDAIYF5pRu+rV1pw9SGr4YoAZiqAy1ZoWQG8+OKLZfHixXLVVVfVfks6K5jewk1n8bp06SKnnnqqHH744bVfT2cR1113XUkimM4Azpo1a7mzfenPzjvvPOnevXudApiKV9IjvZ4WLZrLwoV/laVLS3pla/a1ROfafsQTazYAxU+f3X8vxVQZI9H76pUiXH3Iari2bNnc58lkctQmSwsTwHTzx/vvv1+9PVzzSGcA7777brn33nulW7du0rNnTzn22GOXOwO4xRZbVNcK7r777jJjxgz56U9/Wq8zgEuWfC1Nm66VSdw8TQisOQJbD7p/zf1w5U9+Z9hByknGIAABCDRuAsUJ4J133ikTJ06UBx98sJZ8ugZw0aJFcvXVV8v5558vG220UXVnb80jXQN40kknVXcK77XXXtWNJQceeGD15fRWc801gK1atVopzXQNIGcAG3fJG8uz0/wNtbE894Z4HpwBbAiKq+8Y0fvqRRquPmQ1XDkDWNgZwI8++qi6CzidzevVq5ekO4VPP/306mNf0ke6PP3009XX0r+3a9euugs4/XO683fjjTeWkSNHyiOPPFL9WbrGMN0FnG4ESWcR63pwE4jPL3OJ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339/ufrqq+V3v/udjBgxQt59913ZYost5IILLpB99tmn9vvGjx8vkydPlk8++UR23nlnGTJkiGy77bZ1thYB9PllLvGomgVVEgcEMK80o/fVKy24+pDVcEUACxXA4cOHy//93//JlVdeuVzb3nnnHenWrZtcc801svfee8vDDz8sF154YfW/P/7xj2XatGly7bXXys033yytWrWq/vmpp56SGTNmSJPUsBUeCKDPL3OJR9UsqJI4IIB5pRm9r15pwdWHrIYrAlioAB577LFywAEHSK9evZZrWxK6V199VW655ZbaP+/Tp4/ssssuctZZZ8nRRx8tnTt3lr59+1ZfX7x4sXTo0EHGjBkjHTt2RAB9fndDHFWzoEoCgwDmlWb0vnqlBVcfshquCGCBAvj1119Lu3btpH379vLWW2/JkiVLKqlLbwlfdNFFstVWW8mgQYNqWzhs2DCZO3duJXm77babpLOH++67b+3Xe/ToUZ01POGEE+oUwDpODPo0fDUdNb2eFi2ay8KFf5WlS1fTDw3wY6JzbT/iiexSnt1/r+yec0M94eh9bSiOKx4Hrj5kNVxbtmzu82QyOWqTpQUK4IIFC+Tss8+WQw89VA466CD56KOPZODAgdKsWTP58ssvpW3bttXXax4jR46Ul156SW699VbZaaedqrd/99hjj9qvH3PMMdKpUyc5/fTTV4p1yZKvpWnTtTKJm6cJgTVHYOtB96+5H678ye8MO0g5yRgEIACBxk2gSAGsC/krr7wiPXv2rN7OTZKXhLDmkc4AphtCbrjhhurMYbpBZNmbQtIZwO7du8vxxx/PGcDG3edG/ew0f0Nt1C9oFZ8cZwBXEdga/vboffXCD1cfshqunAEs8AzgG2+8Ib/5zW/k/PPPr71xY/bs2XLcccfJv//7v8vrr78uEyZMqG1hugbwZz/7mZxzzjly1FFHVW//nnLKKdXXa64BTHK47FnBmmFuAvH5ZS7xqJprVEriwDWAeaUZva9eacHVh6yGK9cAFiiA7733XnUDSHrL9sQTT5T3339fzj33XGndurWcdNJJ1VvD6axf165dq7t/0/WA06dPl2222UamTp0qo0ePlnHjxlX/nm4aefTRR+X++++XddZZp84zgD51XnNH1fwirblnm89Pjs4VAcynq+mZRu+rV1pw9SGr4YoAFiiAqV7PPfdc9VEv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\" width=\"640\">" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"returns = option_series.to_returns().dropna()\n", | |
"ax = returns.hist()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 44, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2018-10-06T17:17:23.572359Z", | |
"start_time": "2018-10-06T17:17:23.469598Z" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Stat Options\n", | |
"------------------- ----------\n", | |
"Start 2006-05-17\n", | |
"End 2018-09-21\n", | |
"Risk-free rate 0.00%\n", | |
"\n", | |
"Total Return 469.57%\n", | |
"Daily Sharpe 0.66\n", | |
"Daily Sortino 1.16\n", | |
"CAGR 15.13%\n", | |
"Max Drawdown -26.90%\n", | |
"Calmar Ratio 0.56\n", | |
"\n", | |
"MTD -2.92%\n", | |
"3m -9.15%\n", | |
"6m -5.80%\n", | |
"YTD -10.35%\n", | |
"1Y 1.22%\n", | |
"3Y (ann.) 7.83%\n", | |
"5Y (ann.) 10.35%\n", | |
"10Y (ann.) 19.86%\n", | |
"Since Incep. (ann.) 15.13%\n", | |
"\n", | |
"Daily Sharpe 0.66\n", | |
"Daily Sortino 1.16\n", | |
"Daily Mean (ann.) 17.99%\n", | |
"Daily Vol (ann.) 27.32%\n", | |
"Daily Skew 1.53\n", | |
"Daily Kurt 45.51\n", | |
"Best Day 28.79%\n", | |
"Worst Day -23.63%\n", | |
"\n", | |
"Monthly Sharpe 0.73\n", | |
"Monthly Sortino 2.27\n", | |
"Monthly Mean (ann.) 17.82%\n", | |
"Monthly Vol (ann.) 24.25%\n", | |
"Monthly Skew 2.00\n", | |
"Monthly Kurt 7.04\n", | |
"Best Month 40.72%\n", | |
"Worst Month -10.86%\n", | |
"\n", | |
"Yearly Sharpe 0.64\n", | |
"Yearly Sortino 2.43\n", | |
"Yearly Mean 17.49%\n", | |
"Yearly Vol 27.31%\n", | |
"Yearly Skew 0.13\n", | |
"Yearly Kurt -1.19\n", | |
"Best Year 61.33%\n", | |
"Worst Year -21.49%\n", | |
"\n", | |
"Avg. Drawdown -5.26%\n", | |
"Avg. Drawdown Days 65.39\n", | |
"Avg. Up Month 6.55%\n", | |
"Avg. Down Month -3.18%\n", | |
"Win Year % 66.67%\n", | |
"Win 12m % 76.09%\n" | |
] | |
} | |
], | |
"source": [ | |
"stats = option_series.calc_stats()\n", | |
"stats.display()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"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.6.5" | |
}, | |
"varInspector": { | |
"cols": { | |
"lenName": 16, | |
"lenType": 16, | |
"lenVar": 40 | |
}, | |
"kernels_config": { | |
"python": { | |
"delete_cmd_postfix": "", | |
"delete_cmd_prefix": "del ", | |
"library": "var_list.py", | |
"varRefreshCmd": "print(var_dic_list())" | |
}, | |
"r": { | |
"delete_cmd_postfix": ") ", | |
"delete_cmd_prefix": "rm(", | |
"library": "var_list.r", | |
"varRefreshCmd": "cat(var_dic_list()) " | |
} | |
}, | |
"position": { | |
"height": "416px", | |
"left": "1163px", | |
"right": "20px", | |
"top": "127px", | |
"width": "356px" | |
}, | |
"types_to_exclude": [ | |
"module", | |
"function", | |
"builtin_function_or_method", | |
"instance", | |
"_Feature" | |
], | |
"window_display": false | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment