Skip to content

Instantly share code, notes, and snippets.

@AnthonyFJGarner
Last active March 20, 2023 00:12
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save AnthonyFJGarner/18485f4413c521300a7f76b5e8a02b90 to your computer and use it in GitHub Desktop.
Save AnthonyFJGarner/18485f4413c521300a7f76b5e8a02b90 to your computer and use it in GitHub Desktop.
Vix Options - Mean Reversion System
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"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": 23,
"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>48.837349</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2002-07-31</td>\n",
" <td>49.285275</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2002-08-01</td>\n",
" <td>49.488335</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2002-08-02</td>\n",
" <td>49.870586</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2002-08-05</td>\n",
" <td>50.121433</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Date Adj Close\n",
"0 2002-07-30 48.837349\n",
"1 2002-07-31 49.285275\n",
"2 2002-08-01 49.488335\n",
"3 2002-08-02 49.870586\n",
"4 2002-08-05 50.121433"
]
},
"execution_count": 23,
"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": 24,
"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": 25,
"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>58.414406</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2006-02-28</th>\n",
" <td>58.647667</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2006-03-01</th>\n",
" <td>58.532089</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2006-03-02</th>\n",
" <td>58.298084</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2006-03-03</th>\n",
" <td>58.156284</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" bond\n",
"Date \n",
"2006-02-27 58.414406\n",
"2006-02-28 58.647667\n",
"2006-03-01 58.532089\n",
"2006-03-02 58.298084\n",
"2006-03-03 58.156284"
]
},
"execution_count": 25,
"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": 26,
"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": 26,
"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": 27,
"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": 27,
"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": 28,
"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": 28,
"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": 29,
"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": 29,
"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": 30,
"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": 30,
"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": 31,
"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>58.414406</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>58.647667</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>58.532089</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.298084</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.156284</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 58.414406 \n",
"2006-02-28 58.647667 \n",
"2006-03-01 58.532089 \n",
"2006-03-02 58.298084 \n",
"2006-03-03 58.156284 "
]
},
"execution_count": 31,
"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": 32,
"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": 33,
"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": 34,
"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": 35,
"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>101.540001</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>101.120003</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>100.949997</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>100.959999</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>101.000000</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 101.540001 \n",
"2018-09-18 13.91 16.0 False False 101.120003 \n",
"2018-09-19 13.91 16.0 False False 100.949997 \n",
"2018-09-20 13.91 16.0 False False 100.959999 \n",
"2018-09-21 13.91 16.0 False False 101.000000 "
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"combined.to_csv('../data/Options/combined2.csv')\n",
"combined.tail()"
]
},
{
"cell_type": "code",
"execution_count": 84,
"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",
" if row.put_mid_underlying > 40:\n",
" put_allocation = 0.14\n",
" call_allocation = 0.00\n",
" bond_allocation = 0.86\n",
" elif row.put_mid_underlying < 8:\n",
" put_allocation = 0.00\n",
" call_allocation = 0.06\n",
" bond_allocation = 0.94\n",
" else:\n",
" put_allocation = 0.00\n",
" call_allocation = 0.00\n",
" bond_allocation = 1\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": 85,
"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>362530.0</td>\n",
" <td>108759.0</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>0.0</td>\n",
" <td>0.0</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>9459.0</td>\n",
" <td>960466.869459</td>\n",
" <td>-135979.288587</td>\n",
" <td>933246.580872</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>362530.0</td>\n",
" <td>108759.0</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>0.0</td>\n",
" <td>0.0</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>9459.0</td>\n",
" <td>956494.108377</td>\n",
" <td>-135979.288587</td>\n",
" <td>929273.819790</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>362530.0</td>\n",
" <td>108759.0</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>0.0</td>\n",
" <td>0.0</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>9459.0</td>\n",
" <td>954886.021623</td>\n",
" <td>-135979.288587</td>\n",
" <td>927665.733036</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>362530.0</td>\n",
" <td>108759.0</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>0.0</td>\n",
" <td>0.0</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>9459.0</td>\n",
" <td>954980.630541</td>\n",
" <td>-135979.288587</td>\n",
" <td>927760.341954</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>362530.0</td>\n",
" <td>108759.0</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>0.0</td>\n",
" <td>0.0</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>9459.0</td>\n",
" <td>955359.000000</td>\n",
" <td>-135979.288587</td>\n",
" <td>928138.711413</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 362530.0 108759.0 False \n",
"2018-09-18 13.91 362530.0 108759.0 False \n",
"2018-09-19 13.91 362530.0 108759.0 False \n",
"2018-09-20 13.91 362530.0 108759.0 False \n",
"2018-09-21 13.91 362530.0 108759.0 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 0.0 \n",
"2018-09-18 53 days 00:00:00.000000000 13.91 0.0 \n",
"2018-09-19 53 days 00:00:00.000000000 13.91 0.0 \n",
"2018-09-20 53 days 00:00:00.000000000 13.91 0.0 \n",
"2018-09-21 53 days 00:00:00.000000000 13.91 0.0 \n",
"\n",
" call_position_value call_entry call_exit bond_position \\\n",
"Date \n",
"2018-09-17 0.0 False False 9459.0 \n",
"2018-09-18 0.0 False False 9459.0 \n",
"2018-09-19 0.0 False False 9459.0 \n",
"2018-09-20 0.0 False False 9459.0 \n",
"2018-09-21 0.0 False False 9459.0 \n",
"\n",
" bond_position_value cash equity_curve \n",
"Date \n",
"2018-09-17 960466.869459 -135979.288587 933246.580872 \n",
"2018-09-18 956494.108377 -135979.288587 929273.819790 \n",
"2018-09-19 954886.021623 -135979.288587 927665.733036 \n",
"2018-09-20 954980.630541 -135979.288587 927760.341954 \n",
"2018-09-21 955359.000000 -135979.288587 928138.711413 "
]
},
"execution_count": 85,
"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": 86,
"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": 87,
"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": 87,
"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": 88,
"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": 88,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"option_series.rename(columns={'equity_curve': 'Options'}, inplace=True)\n",
"option_series.head()"
]
},
{
"cell_type": "code",
"execution_count": 89,
"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,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAgAElEQVR4XuydB5QU1baGfxhyDkMacs5JchhBBAwYUFQUEyqgqCgKXrPXeNVnABFRQBBRRAVEQAGRJDkHyZkhwwxxSMOkt6qGbnrirq7T3VN9+q+13ro4Z+9TZ3+1a/f/TtU5lSM5OTkZPEiABEiABEiABEiABEKGQA4KwJC51gyUBEiABEiABEiABEwCFIBMBBIgARIgARIgARIIMQIUgCF2wRkuCZAACZAACZAACVAAMgdIgARIgARIgARIIMQIUACG2AVnuCRAAiRAAiRAAiRAAcgcIAESIAESIAESIIEQI0ABGGIXnOGSAAmQAAmQAAmQAAUgc4AESIAESIAESIAEQowABWCIXXCGSwIkQAIkQAIkQAIUgMwBEiABEiABEiABEggxAhSAIXbBGS4JkAAJkAAJkAAJUAAyB0iABEiABEiABEggxAhQAIbYBWe4JEACJEACJEACJEAByBwgARIgARIgARIggRAjQAEYYhec4ZIACZAACZAACZAABSBzgARIgARIgARIgARCjAAFYIhdcIZLAiRAAiRAAiRAAhSAzAESIAESIAESIAESCDECFIAhdsEZLgmQAAmQAAmQAAlQADIHSIAESIAESIAESCDECFAAhtgFZ7gkQAIkQAIkQAIkQAHIHCABEiABEiABEiCBECNAARhiF5zhkgAJkAAJkAAJkAAFIHOABEiABEiABEiABEKMAAVgiF1whksCJEACJEACJEACFIDMARIgARIgARIgARIIMQIUgCF2wRkuCZAACZAACZAACVAAMgdIgARIgARIgARIIMQIUACG2AVnuCRAAiRAAiRAAiRAAcgcIAESIAESIAESIIEQI0ABGGIXnOGSAAmQAAmQAAmQAAUgc4AESIAESIAESIAEQowABWCIXXCGSwIkQAIkQAIkQAIUgMwBEiABEiABEiABEggxAhSAIXbBGS4JkAAJkAAJkAAJUAAyB0iABEiABEiABEggxAhQAIbYBWe4JEACJEACJEACJEAByBwgARIgARIgARIggRAjQAEYYhec4ZIACZAACZAACZAABSBzgARIgARIgARIgARCjAAFYIhdcIZLAiRAAiRAAiRAAhSAzAESIAESIAESIAESCDECFIAhdsEZLgmQAAmQAAmQAAlQADIHSIAESIAESIAESCDECFAAhtgFZ7gkQAIkQAIkQAIkQAHIHCABEiABEiABEiCBECNAARhiF5zhkgAJkAAJkAAJkAAFIHOABEiABEiABEiABEKMAAVgiF1whksCJEACJEACJEACFIDMARIgARIgARIgARIIMQIUgCF2wRkuCZAACZAACZAACVAAMgdIgARIgARIgARIIMQIUACG2AVnuCRAAiRAAiRAAiRAAcgcIAESIAESIAESIIEQI0ABGGIXnOGSAAmQAAmQAAmQAAUgc4AESIAESIAESIAEQowABWCIXXCGSwIkQAIkQAIkQAIUgIo5EB0dK/ZQokRBnDp1QbQLZQMykq8+GZGRTEC2YB6RkUxAttAhj0qVKiwHqrEFBaDixZUEYI4cQHh4YcTExCI5WfFkmrqTkXxhyYiMZAKyBfOIjGQCsoUueUQBmExZIqd75hYUgCr0Unx1KSbqJDLvgYxkumRERjIB2YJ5FDqMKAApAOVsz8KCAlAJHwWgRXz8UZJBkREZyQRkC+ZR6DCiAKQAlLOdAlCJkeTMgisR4iypTIiMyMgKAdmG9Sh0GFEAUgDK2U4BqMRIcmbBlQhR3MiEyIiMrBCQbViPQocRBSAFoJztFIBKjCRnFlyJEMWNTIiMyMgKAdmG9Sh0GFEAUgDK2U4BqMRIcmbBlQhR3MiEyIiMrBCQbViPQocRBSAFoJztFIBKjCRnFlyJEMWNTIiMyMgKAdmG9Sh0GFEAUgDK2U4BqMRIcmbBlQhR3MiEyIiMrBCQbViPQocRBSAFoJztFIBKjCRnFlyJEMWNTIiMyMgKAdmG9Sh0GFEAUgDK2U4BqMRIcmbBlQhR3MiEyIiMrBCQbViPQocRBSAFoJztFIC2GB08eAAVK1YSfVlwRUT8WoqMiIzIyAIB2YT1KHQYUQBSAMrZHoICcMeO7fjhh7HYsGEd4uLiUKJESURGdsQjjzyGIkWKisymTPkVCxfOw5dfjjRtH3roPtO3a9db0vmy4Io4KW5kRGRERhYIyCasRzKjs5fjMXXrCSTEJeCWeqVRvmh+2cmBFhSAFIDp0nLEiBFYvHgxrly5ggEDBqBjx46Zpq6On4JbunQx3nrrFdx3Xy/06HEfSpYMx4EDURg58its374Vo0aNQ3h4qSxv5zFjRmL9+rUYPnyUeNuz4IqIKG5kRGRERhYIyCasRzKj8asP4stF+9yGU59ogQrFgk8EUgBSAKbK9hUrVuCnn37CsGHDcPLkScyYMQO9e/f2mQA0cF9OSJLvMB9Z5MuVEzmMimbxMETvPffcjrvvvhe9e/dJ5ZWUlIRnnumDUqXKoHXrtvj99ymoUaMm5s6dg/z58+Guu+7Fo48+gdmz/8THH78Pw75AgQKYPXuh2efjj/fDrbfejri4yzAEouF38eJF1KxZE6+99ioiIqoiORlo3745Bg4cDGMWMSYmBjVq1MDgwa+hevUaSEhIwNChn2LRogVITExA5cpV8dRTz6JRoyYWIwxOM/4oydeNjMhIJiBbMI9kRs9N2YTl+0+7DQffUB09rysvOzrMggKQAjBVSn722WeIj4/H/v37zf994403ULVqVZ8IwKSkZPT5eSP+PXIuYLdB44giGH1/Y8sicN26NXjuuacwefIfKFu2bLpx/vHHNHz66YcYNOgVU+T17NkL/fo9g3379mDQoAHo338AbrutuynwPGcAPQXgBx+8jZ07d+CDD/4PZcqUxe+/T8a3336D8eN/Mf/bEIANGjQy2/PmzYc33vgPcuYMw+eff4k//5yOSZN+Nh8tG+LS8Fu2bAm+/35iwJhmx4n4oyRTJyMykgnIFswjmVHPcWuw9+RFt+GDzSpgYMdqsqPDLCgAKQBTpeTrr79uzvwNHz4cW7duxUcffWTOCGZ2ePMI2BCAfX/eiI0OFoBz5szGu+++gQULliN37tzpwl6xYhkGD34OTz75LH7++QdMm/YXcuXKZdoZj4g3bdpoPvbNTADeeGNX3HxzR/zvf5+gTZv2pp9RcJ966jG0a9cBDz3U2xSAb7/9ATp3vslsnz59Kn74YRwmTZqGuXP/wief/A+9e/c1ZyErV66CnDlzOqys+H44/FGSmZIRGckEZAvmUdaMDMnQ8vPFplHDcoWx6WgsOlQviU+715fhOsyCApACMFVKfvLJJ4iIiMCDDz5o/r1Tp06YP3++TwSg8XjT6Y+AXTOAEyf+luEK3qlTJ+OLLz41ZwCNR8BjxvzgZmPM5P3yy08wfDMTgC1btkH37jdjwoTJpnhzCcD3338TefLkx0svvWYKwGHDvsF11zU322fOnIGxY0dh8uQZ5n/PmvUHjJnIrVs3o3jxEubiku7d73FYafHtcPijJPMkIzKSCcgWzKOsGc3bGY1XZmwzjd64qSbe/2uX+e9VL0ZaftIkX4XAWFAAUgCmyrR58+Zh0qRJ+Oabb8zHwIMGDcKUKVN8JgADk9b2z2K8Y9ejRzfcfPNt5uNczyMxMdGcqTMe07ZtG2nO+P3++yz3TT9ixDDs3LkdQ4eOyFQA3nxzN3TuHIn33/8YbdtemwHs1+9RtG7dDo891i9LAWgsRjHGWK1adfNdwvnz58J4pGw8Pjb+puvBHyX5ypIRGckEZAvmUdaM3p69A39uOW4azXumDW78arn576F3NUC7aiVkwA6yoACkAEyVjgYO47HvunXrzNm6t956C40aNQoZAWgEunLlcrz++kvmKmBjMYixBUxU1H6MHDkc27alrAJeu3Y1/ve/d/Dkk8/ggQceNoXfoEHPYfDgV2A85jUe2S5Y8DfGjPnRFIie7wB+9tnH+PffDaneAfzmm+EYN+4nVKxYOUsBOHHij5g27TcMGTIc5cpFmO//vfrqIEyaNB2lS5dxUGnx7VD4oyTzJCMykgnIFsyjrBm1/2IJ4q4uZFwz+Ho0/3SR6fDhbXXRuXbWu0PI9ANrQQGouQA8deoUevbsiffffx+tWrUys8t4x+/NN9/EqlWrEBYWhjvuuAMvv/yy+102b1LQm3cAjUfAwXLs2rUTP/74nbkP4IULF67uA9gBDz/8OIoVK2Y+ljVmAI2ZwEWL5qNAgYKmEDQEo3Hs3bsHL730PGJjYzFlyh947LFe7lXAly9fxtixIzFv3t84d+6cubr3lVf+g6pV67hXAWf2CNiY/fv662HmCuILF86jbNkI9O37FDp06BQsaG2Nkz9KMjYyIiOZgGzBPMqaUbeRK3Di/BUUzpsLCwa0xbOTNmFF1Gm8c0tt3FrP2v8THp+YZD5GLpY/FyKrlcSEtYcwrEdD5M8dJl8gH1pQAGosANeuXYtXXnkFBw4cwPjx490C8OGHH0aZMmXw3nvvmduM9O/fH927d0efPqm3PbGSZ4YAzGqXFaOtZMnCOHky1hQ3uhx//pnyXt6UKSnv5akcujJSYZLWl4xkmmRERjIB2YJ5lDWjjl8uxfm4RMwb1AHFcibjP9O2Yt7OGAzuVB33W9wKZu6Oa+8Rus6WMwewatD18gXyoUV4eGEf9hZ8XeVI1lQATp061dzL76WXXsILL7zgFoBRUVHo2rUrFi1aZIpA45g5cyaMxR8LFizw+gomJiYhLEz/Vahpwfz222/mSumsFsh4DZMOJEACJEACjiZQ47WZSEhKxopXb0TZovnw3h9bMWbJPvSNrIrXu9WzNPahc3di6NyUxSOex3ePtcCIBbtRqnBefHpvYxTIk7LDBA//ENBWAEZHR6N48eLmY93atWu7BeDcuXNhbPWycuVKN9EdO3aYj4FXr16NIkWKeEWaM4CcAfQqYWwac1ZCBkdGZCQTkC2YR5kzMh7dthmyxDTY+N+uSLh4GRPXHsan8/fgxlrh+PgOWQBeupKIyGFLxQvx0e3+f6eQM4CazgB6ZpenAJw2bRqGDBmChQsXuk2MR8RdunTBP//8k+Hmx1llqq7vAIp3pw8N+M6NDJOMyEgmIFswj8hIJpCyXZlxpP2K1NFzl3HH6FVm2873b8G5MxewcFcMBk/bivplC2Pcg00z7X5l1Gl8tXif2efWY7HiMF7oWA29mlUQ7VQM+A5giAnAv//+2/y6R0YzgGvWrEHhwt69E0ABqHL7pfjyR0lmSEZkJBOQLZhHZGQQSExKxqYj51CjVEEUypv+MeubM7dj9rYTKJgnDPOeaYsw4wU9AH9sOYZ3Zu80/73/o26IiYnFuoNn0e+XjebfapYqiK61S6F3q0rpQLf4LGW1sNWjbOG8mNEvZeGmvw4KwBATgMbefjfddBOWLl2K8PBwM6+MdwA//vhjcwbQ24MC0Fti6e35oyQzJCMykgnIFsyj0GZ04UoCCubJhdHLozBqWRTaVyuBIXc1yFKsta1aHF/c3dC0uWvMKhw6cxmPtqyId+5uZArAfScv4t7v1qTqw9gf0Fgl7DmDmFYAGue+kpCE1QfOoGudUvhre3S6cax4IdItPuUr570FBWCICUAjRXr16mU+6n333Xdx+vRpcxWwIQoHDEi98bGVdKIAtEIpaxv+KMkMyYiMZAKyBfModBkNmJyyXUuf1pXw7YoDbhArX4xEzjRbWXT+ahnOXk5w2xjv4xmH6wsg/dpWxmt3NDAFoPG0OKPZvZ5NIzC4Uw3Tz/Pzca5O72xQFm/cVMtcUHI5PhE3DF9mNuXKmcP8m3Hc3agcXu1SU75oNi0oAENQABpbvxjiz3gMbHxH1tgCZvDgweaegN4eFIDeEktvzx8lmSEZkZFMQLZgHoUuo8wewT53fVU83KJiKjDGVi8XriRmCmvEvQ1xa7NKbgEY+cUSXL66ObSn05/9WqF04by4FJ+I69Ms/BjZsxGuq1DMbe4a30PNK+DHNYfcfx//UFPULePdq1nyVU6xoAAMAQFoNRns2FEA2qGW2oc/SjJDMiIjmYBswTwKXUaZCcC8uXJiyfMpn+U8du4ynpm8CQdOX8oS1OpBkShVqohbAP6w+iCGLdqXzseYKby9fhn8tPYwJq47bLYbi0V6NSuPrnVKp7LfePgsZm49gZdurIE2QxanavujXyuUKZxXvnheWlAAUgB6mTKpzSkAlfCZzvxRkhmSERnJBGQL5lFoMjoeG4fbRl3b+iwthdVXN2Du9/MGrD98LktI/7mxBu5rGgFjCxXXI2DDwVhYMm9nNF7/czvy5cqZ4YygYec6V1Yn+Xrpfoz1eEz9fIdqMGYGfX1QAFIAKuUUBaASPgpAi/j4wy2DIiMykgnIFjrmkbQC1xBlScnJaPX5tZm3QTdUx5zt0dh0NEUQ1ggviJaVi8GY1TNWDqcVgJ5kp2w8go/m7k4H+94mETAEpJXDkCZbj5/H8n2nzC+MZLRa2Uo/WdlQAFIAKuUQBaASPgpAi/h0/FGyGLplMzKSUZFRaDEyFlP8d+Z2zNmRfoXt611q4oO/03+Nw0Vo+cD25grcSRuO4sT5OPRtUxnG42LjkPLI2DC67dCUDaM9Dyuzf/IV8p0FBSAFoFI2UQAq4bNUTNTPEPw9SAU3+CNUj4CMZIZkFFqMMpuJMyhM69MSd36bsqlzRkdWYs1KHs3cehz/nbXD3XWnmta+FCJfId9ZUABSACplEwWgEj4KQIv4rBRci11pa0ZG8qUlo9BgtPbgGRjv/XkKsOE9GuL3Tccwd2c0mpYvglH3N0Gv8WuxK/qCXwSgMfvYe8J6HDpzCS93roGONcKRP7f3O23IV8y+BQUgBaD97AFAAaiEjwLQIj7+cMugyIiMZAKyRbDn0YJdMfjP9K2pAp31VGuEF8xjirFFe07itvplUCRfbgz+fQv+2XMylW2FYvnwWpeaaFGpeKawrDIyFoYY/5fn6qNjmX5gLSgAKQCVMo4CUAkfBaBFfFYLrsXutDQjI/mykpH+jPr/uhFrDp51B9qyUjF8dW+jDAPfFX3enCV8ql0VzNp63Fxo8XrXWiIkXfKIApACUEz2rAwoAJXwUQBaxKdLwbUYri0zMpKxkZH+jNKu+F04oK35+TdfHrrkEQUgBaDSfUEBqISPAtAiPl0KrsVwbZmRkYyNjPRmdCI2Dt089vv7rlcTNChXRA7aSwtd8ogCkALQy9RPbU4BqISPAtAiPl0KrsVwbZmRkYyNjPRm5PlJtlUvRiKHccH9cOiSRxSAFIBKtwcFoBI+CkCL+HQpuBbDtWVGRjI2MtKTUdovfZQokBt/9W8jB2vTQpc8ogCkALR5C6S4UQAq4aMAtIhPl4JrMVxbZmQkYyMjPRk9OmE9th6LdQf3Wff6uL56STlYmxa65BEFIAWgzVuAAlAJnIezLsXEVzwy6oeMZLpkREYyAdkiGPOozZDFMPbdcx1/9GuFMoXzysHatAhGRhmFSgFIAWjzFqAAVAJHAegVPl0KrldBe2lMRjIwMtKP0ZmL8ejy9fJUgfnz/T/jRLrkEQUgBaBcEbKw4CNgJXymsy7FRJ1E5j2QkUyXjMhIJiBbBFse9Ri7GgdOX3IH9umd9dChRrgcqIJFsDHKLFQKQApAhduA7wAqwbvqrEsx8QWLzPogI5kuGZGRTEC2CEQeXYpPhLE+N5/NT6ONWRGFUcui8M+AdogcttQdVFbf75Ujt24RCEbWR2PfkgKQAtB+9nARiBI7l7MuxcQnMDLphIxkumRERjIB2cIfebTjxHmcj0tAs4rF8Mm83fh1wxFzIHYf1abd7Nno6+5G5fBql5pygD6w8AcjHwzL6y4oACkAvU4aTwc+AlbCZzrrUkzUSWTeAxnJdMmIjGQCsoU/8ujmb1bg5IUr6U6+5Pn2yGvjO7kZCcDZT7VGyYJ55AB9YOEPRj4YltddUABSAHqdNBSASsjSOetSTHxLJXVvZCTTJSMykgnIFv7Io4wEmzGSec+0QZF8ueVBpbHIqL9lA9sjd1hOr/uy4+APRnbGoepDAUgBqJRDnAFUwscZQIv4dCm4FsO1ZUZGMjYyCjyjpORktPp8cYYnnvVkK4QX8m67lsz6C9T7f0YguuQRBSAFoFwRsrCgAFTCRwFoEZ8uBddiuLbMyEjGRkaBZxSfmIS2Q5dkeOKpT7RAhWL55UF5WIxdcQBfL92fyidPWA4sHRjpVT8qxrrkEQUgBaDKfcAvgSjRS3HWpZj4AEWmXZCRTJeMyEgmIFv4Oo8uxyemWqnrOYJfejdDtZIF5UF5WHg+/n28VUUUzJMLD7eo4Lfv/mY0OF8z8gqAD40pACkAldKJM4BK+CgALeLTpeBaDNeWGRnJ2Mgo8IyM1b83DF+W4YnbVyuBIXc1kAd11cL4uW7p8Tg5kI99PQepSx5RAFIAWr75MjKkAFTCRwFoEZ8uBddiuLbMyEjGRkaBZ3T2Ujw6j0j9pQ7PUXgj4pbuPYWBUzeb7o0jiuDbB5rIAfnBQpc8ogCkAFS6PSgAlfBRAFrEp0vBtRiuLTMykrGRkX8YGY95f1xzCB1rhKNGqdSPdE9dvIKbvl5hnti171+v8WuxK/pCqr/JIwOMDaC/WRplmq58MRI5jQuaDYcueUQBSAGodPtQACrhowC0iE+XgmsxXFtmZCRjIyP/MBr2z178sOaQ2XnaGb3o83G4deRKhOXMgRUvpCzUGPT7Fizac9I9mHEPNkX9soXFwd0xeiWOnotDt3ql8fYtdUR7fxnokkcUgBSASvcIBaASPgpAi/h0KbgWw7VlRkYyNjLyD6N+P2/A+sPnMhSAx85dxu2jV5kbPhsbPxvHy9O3Yv6umFSDubVeabSvVhJdapfKdJD3f78Ge2IuomfTCAzuVEMOxk8WuuQRBSAFoNItQgGohI8C0CI+XQquxXBtmZGRjM2XjOZsP4HX/9yOsoXz4tfHmiO/ze/ayqMOrIUdRn0mbsDGIxkLwENnLuGuMatRIHcY/nmunRnM639sw5wd0RkGViO8IIbf0zDDr3rc8s0KxFy4gh8eaoo6ZeQZQ3+Rs8PIX2NR6ZcCkAJQJX+4DYwSvRRnXYqJD1Bk2gUZyXTJKLCM7vx2FY6cvZwiaLrURPdG5eQBBIGFnTzy3JplRt+WKFsknzvSqFMXcc93a1A4by7Mf7at+ff/ztqOmVtPZEqjV7PyeKFj9VTtxk91+y+W4EpiMqb3bYlyHucINFY7jAI9RivnowCkALSSJ5nacAZQCR8FoEV8uhRci+HaMiMjGZsvGXmKnux+JClHbt3CG0bG4o93Zu/E3J2pZ/OqlSyAX3o3xz+7T2LwtC3myYvlz42/n25j/nvb8Vg88uP6TAd1b5MI/OfG1I94L8Un4vphS02ffwa0Q4E8YdaD8rGlN4x8fGqfdkcBSAGolFAUgEr4KAAt4tOl4FoM15YZGcnYfMko7fdoZz/VGjlzAMUL5JEH4meLtQfPYMKaQ+jbtjLqevmo1BtGP6w+iGGL9mUYzZ/9WqHbqJXuNs9FIMYf95+8iMTkZPSesB6XE5JS9fFQ8wp4vkM199+Mz7+tijqNAVM2m4yNxSQ5smkFsDEobxj5+VIrdU8BSAGolEAUgEr4KAAt4tOl4FoM15YZGcnYfMmo81fLcPZyQqqTFsobhqmPt0SxArnlwfjJ4vMFezBx3WF3795ul+INo+GL9+H7VQczjOTp9lUwYsm1T7alFYAup+d/24Rl+06n6sN4BPxk2yq4GJ+I4vlzo/WQ1N8S9mbvQH9g9oaRP87vqz4pACkAlXKJAlAJHwWgRXy6FFyL4doyIyMZmy8ZdRi21BQoaY9P76yPDjVKyoPxg0VcQpL5npznYay8NVbgWj28YWR8k9f4Nq+Vo2i+XJj7TMo7gJ7HJ/N249cNR1L97ea6pWFsH7PlaCyqlCiA7SfOu9tfvrEG7mkSYeWUfrPxhpHfBuGDjikAKQCV0ogCUAkfBaBFfLoUXIvh2jIjIxmbLxm1G7rYXJCQ0TH/mbYonC9XpgMyNkc+evYy6pUt7NNHmacvXkHXq5suu07u7fty3jD6ctE+jF+d8Qxg2uDLFcmL6X1bpWPyz+4YDJ621fx7p5rh5vYwxmxhYlJ6thJXOQN8Y+ENI9+c0T+9UABSACplFgWgEj4KQIv4dCm4FsO1ZUZGMjZfMmr1+SIYGqVkwTw4eeFKupMveq5dhlvDzN0RjVf/2Gbaf9mjAVpXKSEP3KJFzPk43DLy2nt3htu8Z9qgSD7rj6S9YZT2Pcishmns8/dOBps3746+gAfGrzVXCY95oAnuG7cmw268jcMiMltm3jCydYIAOVEAUgAqpRoFoBI+CkCL+HQpuBbDtWVGRjI2XzEyZqdc76UZ7/2dj0v/KNgYjevTZ8a/DZF426iVSPCY2TI2Pf7fbXXlgVu0cG26nCcsh3t2csS9DdGiUnGLPVhb4LD56DnsjL6AD//eJfY79oEm+HtHNPq0qZSpEN1x/DzKFc1risCWn6d+3884QXbv+5c2SF/lkQjPzwYUgBSASilGAaiEjwLQIj5dCq7FcG2ZkZGMzVeMPN+1e6RFBYxfnfIZtLRHZLUSiE9MRsOIwhi9PP27cg9cVx4v3pB6vztXH1P/PYryRfOhZWXr4s1z02XP9xO9WTRhhVFWM39921RKFaunCJavEJC277salcWrnWv69FG5lXFkZWOFkeo5AuFPAUgBqJRnFIBK+CgALeLTpeBaDNeWGRnJ2HzF6HxcAm4Yvsw84UudquOT+Xvkk2diMemx5iiUJwzhhfK6LdYdOoMnf/nX/G9vxJvrcWr+3DlxKf7a1irLX4hELmP/FAuHFUZZCUBj1XH3b1eZ3+z1dvyGvbGFjfGYvGLx/OjesFy27veXGS4rjCygznYTCkAKQKUkpABUwsWI1g4AACAASURBVEcBaBGfLgXXYri2zMhIxuYrRmcuxaPLiOXmCRc82xbGV0FqlipovuNmPObN6mhZqRhWHTiTqcnMJ1vhxalb3Ctfjf4L5c18QYlnR0MX7sWEtYfMz9O90qUmBv622Wz25ssZEiNj8+fIqxsye5777kblcF/TCFQPL4ile09h4NSUc3sjYOUr6AwLiZEzRimPggKQAlDOkiwsKACV8FEAWsSnS8G1GK4tMzKSsfmKkfE9WuO7tMak2soXr0914rOX4tH5qjhMO6JShfJg5pOtsXz/KTw3JUUgWTmMffGur14SjSKKIHdY5lu6PPnLRqw7dBY31SmF97vVRdcRy3H6UjwmPtoMxjd2rRwSI+Ndxpu/WZGqq861SuHD26+9y2j8rP66/ggqFM+PdlV9t8jFyvgDYSMxCsQYfHEOCkAKQKU8ogBUwkcBaBGfLgXXYri2zMhIxuYrRp6LLZYOjEx34oOnL+HusatT/d3YBmXEvY1QoVh+8++fzt+NX9an3v9OisDzk3PnLsfj5IV4VC1ZAMaXMowHvHeNWY3DZy9jdM/GaFKhqPko1vhvY3WtIR6Nw/jJe++vnciXOyzd59aMdomRK3bXWDtUL4lPu9eXhq5Vu8QoWIKlAKQAVMpVCkAlfBSAFvHpUnAthmvLjIxkbL5gZDwC7fvzRvMRrbHBsrHRckZH2vfkXu9SE90blUtl+sU/e/HjmowXkGQWjTGTN7BDNTw7ZVOmAU99ooUpNHuNX4td0RdSbTfjKeAy2qpGYuRaaOI6ea1SBTHhkWYyfI0sJEbBEioFIAWgUq5SACrhowC0iE+XgmsxXFtmZCRjU2Vk/FzcOnIljEfAriOzd9yW7D2JF6ZuMc2alC+CIXc1yPBdPmPvvpw5c+DilURzBs8Xh+vrH31/3oANh8/hw9vqonPtUmbXK/afMr+p6zqM7+qevRyPsBw5UDR/bnEGcN/Ji6n26ruuQlGM7NnYF8MOmj5U88gpgVIAUgAq5SIFoBI+CkCL+HQpuBbDtWVGRjI2VUbG58kMAeg6Hm5eAc91qCaf2KJF2lnDSsXz48DpSxa9r5m5ROng37fgnz0n8WrnGri7ccrn09KeY+jdDdyLRYwVvMZXOMLDCyMmJhbJGXzoZOeJ83jwh3Xuk310e13cWCtFXIbKoZpHTuFEAUgBqJSLFIBK+CgALeLTpeBaDNeWGRnJ2FQZnYiNQ7erq3yNrVaMz6zlMDr10WGIvR5X3x00Vgt/dW8j8/2+C3GJ6PRVyrYzVg6XAHzvrx2Yvvk4+rergsdbVzI/r+bawDqjfoxPrRXJnytLAbjlWCx6T1jvdn//1jq4qW5pK8PSxkY1j5wCggKQAlApFykAlfBRAFrEp0vBtRiuLTMykrGpMvL81FrVEgXw62PN5ZN6aXHmYjzm7DiBm+uWTvXlDG8+u+YSgF8t3odxqw7i3iYR5oKPPTEXcP/3azMdUTfjc2231slSAK6MOo1nJ197//Db+xujcfmiXkYZ3OaqeeSU6CkAKQCVcpECUAkfBaBFfLoUXIvh2jIjIxmbKiPX9i/GmaqHF8DPj/peAGYWhSQAja1Y5u6MNrddMR7rGseUjUfw0dzdaF+thPkO4tJ9p9yPe59oXQljVqT/OsmgG6rj/rZVkSPuSoaPgD3H8fbNtdGtfhkZvGYWqnnkFBwUgBSASrlIAaiEjwLQIj5dCq7FcG2ZkZGMTZWR5x54xsbPPwVw9avx6HVP9AW8N2dnukCN1ch/9G2Fv3dG4+Y6pVE4X8rG0a4NmY0taKb3bYX+v27EmoNnzTbjfb9WGXx312hrXLEYxvRslE4Aen4Cz7DTcZNnOYvkrXKs9OEEGwpACkClPKQAVMJHAWgRn+oPt8XTBLUZGcmXT5WR5wxgdm1/MmDKJqzYf9oM1ljdazzifb9bHVQpUSAdgI2Hz6LPzxvT/d21cXNWs4o31grHR7fXc/t+t/IARizZ7/5vY4HKlMdbyNA1tFDNI6cgoQCkAFTKRQpAJXwUgBbx6VJwLYZry4yMZGyqjDzfAaxduhB+fPg6+aQ+thgweRNWRKUIQGkGblf0efQaf23Frmsos59qjZIF87hXBN9evwxmbDnu1UhDcfGHC5BqHnkF2o/GFIAUgErpRQGohI8C0CI+XQquxXBtmZGRjE2Vkecq4OwSgLujL+CJiRvwcIsK6NOmcpZBGyuI7xi9Csdj41LZuYTjO7N3YPn+0xh5XyPc890aGeBVC+P9wSfbVvbpCmjLJ3eAoWoeOSAEcwgUgBSASrlIAaiEjwLQIj5dCq7FcG2ZkZGMTZWR51c0Av0OoGd0CUnJyGV8iNjiYcxcvvbHNqw/fA6tKhfD8HsauT2NrWGMvf+ML5LM2X7CXNTx6fw9mfY8/J6GaFW5uMUz62mmmkdOoUIBSAGolIsUgEr4KAAt4tOl4FoM15YZGcnYVBnN2HwM7/6VsgjD+Abvr70DtwpYji5ri4TEJGw+GmuO2/jiR2bHmUtX0GXEigybH29VEf3bV1UdStD7q+aRUwBQAFIAKuUiBaASPgpAi/h0KbgWw7VlRkYyNlVGnosmdF0EYTDKVzg/2n04D2cvJ2DhgLbImSMH8uXKGbKPfNNmlmoeyZkaGAsKQApApUyjAFTCRwFoEZ8uBddiuLbMyEjGpsrIUwBGFM2HaX1ayicNMgsXoxPR55CQmIzcYTmDLAL/D1c1j/w/QmtnoACkALSWKZlYUQAq4aMAtIhPl4JrMVxbZmQkY1Nl5CkAyxTOiz/6tZJPGmQWqoyCLFxbw9WFEQUgBaCtG8DlRAGohI8C0CI+XQquxXBtmZGRjE2VkacANLZRMbZT0e1QZaQbj4zi0YURBSAFoNL9SgGohI8C0CI+XQquxXBtmZGRjE2VkacALJovF+Y+01Y+aZBZqDIKsnBtDVcXRhSAFIC2bgDOACphS+WsSzHxHZH0PZGRTJeM/MvIcwsY40xNyxfBqPubyCcNMgvmkXzBdGFEAUgBKGd7FhacAVTCxxlAi/h0KbgWw7VlRkYyNhVGxgbMD4xf6z7Jn/1aoXThvPJJg8xChVGQhWp7uLowogCkALR9ExiOFIBK+CgALeLTpeBaDNeWGRnJ2FQYbTpyDo9P3GCeZOjdDdCuagn5hEFoocIoCMO1NWRdGFEAUgDaugFcThSASvgoAC3i06XgWgzXlhkZydhUGK2MOo1nJ28yTzKsRwO0qUIBKBPX00Ilj5xEhAKQAlApHykAlfBRAFrEp0vBtRiuLTMykrGpMJq/Mxovz9hmnkTnz6GpMJKvgB4WujCiAKQAVLojKQCV8FEAWsSnS8G1GK4tMzKSsakwmrn1OP47a4d5EmMDaGMjaB0PFUY68sgoJl0YUQBSACrdsxSASvgoAC3i06XgWgzXlhkZydhUGP2x5Rjemb0TecJyYOnASPlkQWqhwihIQ/Z62LowogCkAPQ6+T0dKACV8FEAWsSnS8G1GK4tMzKSsakwmr7pGN6bsxPtq5XAkLsayCcLUgsVRkEastfD1oURBSAFoNfJTwGohCydsy7FxLdUUvdGRjJdMvIvo9//PYoP/t6FyGol8DkFoAxbYwtd7jUKQApApduUM4BK+DgDaBGfLgXXYri2zMhIxqbC6LeNR/Dh3N3oWKMkPrmzvnyyILVQYRSkIXs9bF0YUQBSAHqd/JwBVELGGUAb+HQpuDZCt+wS7IyMUnzwzGVUKJYPOY1gMjkuXklEbFwCytjYhFmF0eQNR/DxvN24oWY4/u+OepavS7AZqjAKtljtjlcXRhSAFIB27wHTjzOASvg4A2gRny4F12K4tsyCnZHnd3ZnPtkKpQql/8qGUa5bfr7Y5GNnM2YVRr+uP4xP5u/BjbXC8dHtFIC2klQTJ5U8chICCkAKQKV8pABUwkcBaBGfLgXXYri2zIKVUVJyMoYs3Iuf1x12x/1m11q4o2HZdBwOnbmEu8asdv999aDrvWKlwsgY32cL9qBL7VL43211vTpvMBmrMAqmOFXGqgsjCkAKQJX7gDOASvRSnHUpJj5AkWkXZCTTDVZGs7Ydx1szU/bXcx0F84Rh4YB26YLeceI8HvphXToBaAjDskXyIVfOzB8dq9xrCUnJaDMkZebxpjql8H43CkA5I/W1CNZ7Le0VoQCkAFS6SzkDqISPAtAiPl0KrsVwbZkFK6M3Z27H7G0n0sWc0SPef4+cwxNXv8drOHSuFY7OtUvhlRnb0Kd1JTzZrkq6fo6du4xvlkWhbZXiuKluaYSHF0ZMTCySk61jvv/7NdgTc9F0aFiuCMb2amLdOcgsgzWPAolZF0YUgBSASvcNBaASPgpAi/h0KbgWw7VlFqyM7hm7GlGnL5kxP9KiIsavPmj+u0fjcnilc81ULFYfOI2nJ6V8jzejI6NHwq/9sQ1/74hG8fy58fczbVCkWEGcOnUeYVksNPHs2/O9Q+PvNUsVxE+PNLN1jYLBKVjzKJBsdWFEAUgBqHTfUAAq4aMAtIhPl4JrMVxbZsHIKO3s36oXIzFz6wm8PTvlkfDUJ1qgQrH8bh5L957CwKmbM+UzsmcjTNlwFPc1jUDj8kWR9p3Bv/q3xk1fr0DusBz46eFm5ufc8uTKmSXv83EJuGH4MrfN2AeaoGFEEVvXKBicgjGPAs1VF0YUgBSASvcOBaASPgpAi/h0KbgWw7VlFmyMLsUn4vphS92x9m5ZEc9EVsXWY7F4dMJ68+/GI94PPVbczt8ZjZdnbLPEZ8ULkXh5+lb8s+dklvZF8+XCtL4tUTBPrgztDpy+hB5jUxaeXFehKEb2bGzp/MFqFGx5lB2cdWFEAUgBqHT/UAAq4aMAtIhPl4JrMVxbZsHG6PDZS+j+7bUVvR/eVtd8n89YFdzq6lYvBgjPx7ozNh/Du3/ttMRnYIdqGPrPXku2htHT7avgsVaV0tlP2XgEH83dbf69Q/WS+LS7vptAGzEGWx5ZvsA+NNSFEQUgBaDSbUEBqISPAtAiPl0KrsVwbZkFGyPXtiquYCc8fB1qlS5k/ueENYfc4s3zMbDnXoGekKqHF3Av0nD9vUSB3Dh1Md4rlq0qFzNFYINyRczHxMaG1COW7MN3K1PeS+xWvwzevrm2V30Gm3Gw5VF28NWFEQUgBaDS/UMBqISPAtAiPl0KrsVwbZkFG6O0Ym7p8+3d7+MZK3dvH73K5OA5M5eZABz3YFP0vvrYWIK38b9d0fidOZKZ2W7MPn749y789u9R878fal4Bz3eoZsk3WI2CLY+yg7MujCgAKQCV7h8KQCV8FIAW8elScC2Ga8ssmBglJiWj9dV99VzBpl3B++WivRi/+hA61yqFD29P2XcvIwE4p39rFC+QB11GLMeZSxnP+L1zS238d9YO1ClTCLNf6ICpK/fjhalb3JzrlimEbcfPp+P+eOtK2HXiPBbvPWW2zX6qNUoWzGPr+gSLUzDlUXYx1YURBSAFoNI9RAGohI8C0CI+XQquxXBtmQULo8vxiYj0WPxhBJt2ta/xN9f7fi0qFcOIexshI9HomqUz/jfq1EV8OHeX+Qj32cnXtopxLS6JPh+HYvlzI6JsUXMfwK4jlrsfES8f2B7P/bYZqw+cScfe2JT6wpVEjO7ZGE0qFLV1bYLJKVjyKDuZ6sKIApACUOk+ogBUwkcBaBGfLgXXYri2zIKB0d6TF9Dv5404eznBHePX9zZC80rF0sU8bdNRvD9nl/l3Y3bw3OV43PjV8nR2Ge395/kIeUbfluZXQozDk9Er07di7s4YFM6bC/OfbWu2GyuQjZnHMoXz4s+t1zanNt4nnPVUa/OdQN2PYMij7L4GujCiAKQAVLqXKACV8FEAWsSnS8G1GK4ts2BglNEj3My+5+u5+GLxc+1SzRr2a1sZo5ZF4adHrkPNUikLR9IexvYtsXEJqF+2sLvJk9Hpi/GYuO4wutUrg0rFr+01aBhfuJKAjl9e2/uvZaVi+OreRrauS7A5BUMeZTdTXRhRAFIAKt1LFIBK+CgALeLTpeBaDNeWmdMZnb0Uj84jUs/gGRszlyiQ8Tt1nhswR1Yr4X4PzzUjaAeSN4w8xer0vi1R7uosop3zBpOPN4yCKS5fjlUXRhSAFIBK9wUFoBI+CkCL+HQpuBbDtWXmdEYbDp1F3182poots9k/l9FnC/bA2C7G82havghG3W/vW7zeMBq/6qD5WTpjhbHn10hsXZwgcvKGURCF5dOh6sKIApACUOnGoABUwkcBaBGfLgXXYri2zJzOaFXUaTzjsTjj49vrolOtUlnGOnp5lPmo1/N4s2st3NGwrJaMbAXlYyen55GPw7XVnS6MKAApAG3dAC4nCkAlfBSAFvHpUnAthmvLzOmM5u2MxitXP+NmbLg89O6GyJUz60UVP609hCELr33Nw1iMYWzFksPmYgynM7J14X3sREYyUF0YUQBSAMrZnoUFBaASPgpAi/h0KbgWw7Vl5mRG8YlJmLbpGD6etxvtq5XAkLsaWIrx93+P4oO/U1YCG8dz11fFwy0qWvLNyMjJjGwH5WNHMpKB6sKIApACUM52CkAlRpKzLsVEilOlnYxkek5llPbbvrfWK413bqkjBwRg/s5ovHx11tBw+KBbHXStU9qSLwWgPUxOzSN70fjHSxdGFIAUgEp3CGcAlfBxBtAiPl0KrsVwbZk5lVHa1b89m0ZgcKcalmLcE3MB93+/1m074t6GaFGpuCVfCkB7mJyaR/ai8Y+XLowoACkAle4QCkAlfBSAFvHpUnAthmvLzKmMTl28gpu+XuGOqU/rSniyXRVLMRqPjtsOXeK2nft0GxTNn9uSLwWgPUxOzSN70fjHSxdGFIAUgEp3CAWgEj4KQIv4dCm4FsO1ZeZURidi49Bt1Ep3TC/eUB0PXFfecoyTNhzBjuPn0adNJfcXPSw7pzF0KiO78fjDj4xkqrowogCkAJSzPQsLCkAlfBSAFvHpUnAthmvLzKmMDp+9hO7frnbH9Mkd9dCxZritGFWdnMpINS5f+pORTFMXRhSAFIBytlMAKjGSnHUpJlKcKu1kJNNzKqP9py7i3u/WuAMY1bMxmlYoKgfkBwunMvJDqLa7JCMZnS6MKAApAOVspwBUYiQ561JMpDhV2slIpudURrujL+CB8dcWckx4+DrUKp3x93vlKNUsnMpILSrfepORzFMXRhSAFIBytlMAKjGSnHUpJlKcKu1kJNNzKqPtx2Px8I/r3QH83qcFyhfNLwfkBwunMvJDqLa7JCMZnS6MKAApAOVspwBUYiQ561JMpDhV2slIpudURpuOnMPjEze4A/i7fxsUK2B/Ja9MInMLpzJSicnXvmQkE9WFEQUgBaCc7RSASowkZ12KiRSnSjsZyfScymjdoTN48pd/3QEsfyFS/AScHK09C6cysheNf7zISOaqCyMKQApAOdspAJUYSc66FBMpTpV2MpLpOZXRqqjTeGbyJhTNlws/P9oM4YXyysH4ycKpjPwUrq1uyUjGpgsjCkAKQDnbKQCVGEnOuhQTKU6VdjKS6TmV0dJ9pzDwt82oU7oQfnj4OjkQP1o4lZEfQ/a6azKSkenCiAKQAlDOdgpAJUaSsy7FRIpTpZ2MZHpOZfTP7hgMnrYVDcsVxtheTeVA/GjhVEZ+DNnrrslIRqYLIwpACkA52ykAlRhJzroUEylOlXYykuk5ldG8ndF4ZcY2NC1fBKPubyIH4kcLpzLyY8hed01GMjJdGFEAUgDK2U4BqMRIctalmEhxqrSTkUzPqYxmbj2O/87agVaVi2H4PY3kQPxo4VRGfgzZ667JSEamCyMKQApAOdspAJUYSc66FBMpTpV2MpLpOZXRL+sO49MFe9C5Vjg+vL2eHIgfLZzKyI8he901GcnIdGFEAUgBKGc7BaASI8lZl2IixanSTkYyPacyGr08CqOWReGuRmXxWpdaciB+tHAqIz+G7HXXZCQj04URBSAFoJztFIBKjCRnXYqJFKdKOxnJ9JzKaMjCPfhp7WE80qICBlxfTQ7EjxZOZeTHkL3umoxkZLowogCkAJSznQJQiZHkrEsxkeJUaScjmZ5TGb0zewf+2HIcz7Svgt6tKsmB+NHCqYz8GLLXXZORjEwXRhSAFIBytlMAKjGSnHUpJlKcKu1kJNNzKqOXpm3Bwt0n8UrnGujROEIOxI8WTmXkx5C97pqMZGS6MKIApACUs50CUImR5KxLMZHiVGknI5meUxn1/3Uj1hw8i/dvrYOb6paWA/GjhVMZ+TFkr7smIxmZLowoACkA5WynAFRiJDnrUkykOFXayUim51RGj/20HpuPxuLTO+ujQ42SciB+tHAqIz+G7HXXZCQj04URBSAFoJztFIBKjCRnXYqJFKdKOxnJ9JzKqNf4tdgVfQFf9miA1lVKyIH40cKpjPwYstddk5GMTBdGFIAUgHK2UwAqMZKcdSkmUpwq7WQk03Mqo3vGrkbU6UsY2bMRrqtQTA7EjxZOZeTHkL3umoxkZLowogCkAJSznQJQiZHkrEsxkeJUaScjmZ5TGd0xeiWOnovDuF5NUL9cETkQP1o4lZEfQ/a6azKSkenCiAKQAlDOdgpAJUaSsy7FRIpTpZ2MZHpOZdTq80VISgZ+euQ61CxVSA7EjxZOZeTHkL3umoxkZLowogCkAJSznQJQiZHkrEsxkeJUaScjmZ4TGcWcj8MtI1eag5/8WHNULlFADsSPFk5k5MdwbXVNRjI2XRhRAFIAytlOAajESHLWpZhIcaq0k5FMz2mMzscloNPwZUi+OvQVL0QiLGcOORA/WjiNkR9Dtd01GcnodGFEAUgBKGc7BaASI8lZl2IixanSTkYyPScxMsrq/83bjckbj5oD79k0AoM71ZCD8LOFkxj5OVTb3ZORjE4XRhSAFIBytlMAKjGSnHUpJlKcKu1kJNNzCqOVUafx7ORNqQb8dPsqeCybPwNnDMgpjOSrmX0WZCSz14URBSAFoJztFIBKjCRnXYqJFKdKOxnJ9LKL0eX4RKw5eAbNKhbDhDWHMHJZVLrBTuvTEhFF88lB+Nkiuxj5OSyfdk9GMk5dGFEAUgDK2U4BqMRIctalmEhxqrSTkUwvuxi9NXM7Zm07kekAW1UuhuH3NJIDCIBFdjEKQGg+OwUZySh1YUQBSAEoZzsFoBIjyVmXYiLFqdJORjK97GLU4rNFWQ6ucUQRfPtAEzmAAFhkF6MAhOazU5CRjFIXRhSAFIBytlMAKjGSnHUpJlKcKu1kJNPLDkbxiUloO3RJloO7s2FZvNG1lhxAACyyg1EAwvLpKchIxqkLIwpACkA52ykAlRhJzroUEylOlXYykukFmlFCYhLuG7cGB89cznJwI+5tiBaVissBBMAi0IwCEJLPT0FGMlJdGFEAUgDK2U4BqMRIctalmEhxqrSTkUwv0Iz2nryAnuPWZjqwumUKoX/7KmhTpYQ8+ABZBJpRgMLy6WnISMapCyMKQApAOdspAJUYSc66FBMpTpV2MpLpBZrR9E3H8N6cnekGZmz4fPpSPIrly4VcYTnlgQfQItCMAhiaz05FRjJKXRhRAFIAytlOAajESHLWpZhIcaq0k5FML5CMth2PxSM/rk81qM61wtG8UjH0aBwhDzabLALJKJtCVD4tGckIdWFEAUgBKGc7BaASI8lZl2IixanSTkYyvUAyem7KJizff9oclPGod/xD18kDdIBFIBk5IFxbQyAjGZsujCgAKQDlbKcAVGIkOetSTKQ4VdrJSKYXSEY9x63B3pMXzUHd2aAs3rjJGat8JUqBZCSNxantZCRfGV0YUQBSAMrZTgGoxEhy1qWYSHGqtJORTC+QjHqMXY0Dpy+Zg5rTvzWKF8gjD9ABFoFk5IBwbQ2BjGRsujCiAKQAlLOdAlCJkeSsSzGR4lRpJyOZXqAY7Ym5gPu/T1n926tZebzQsbo8OIdYBIqRQ8K1NQwykrHpwogCkAJQznYKQCVGkrMuxUSKU6WdjGR6gWLUbuhiXElMNgc09+k2KJo/tzw4h1gEipFDwrU1DDKSsenCiAKQAlDOdgpAJUaSsy7FRIpTpZ2MZHqBYuT56bflA9s7bquXrEgFipF8tZxrQUbytdGFEQUgBaCc7RSASowkZ12KiRSnSjsZyfQCwSguIQntv7j26bfVg66XB+Ygi0AwclC4toZCRjI2XRhRAFIAytlOAajESHLWpZhIcaq0k5FMLxCM/txyHG/P3mEOplj+3Pj76TbywBxkEQhGDgrX1lDISMamCyMKQApAOdspAJUYSc66FBMpTpV2MpLpBYKR5+PfYFr966IXCEbylXK2BRnJ10cXRhSAFIBytlMAKjGSnHUpJlKcKu1kJNMLBKMP/96F3/49ag4m2B7/GmMOBCP5Sjnbgozk66MLIwpACkA52ykAlRhJzroUEylOlXYykukFgtG4lQfw1ZL9uL1+Gbx1c215UA6zCAQjh4Xs9XDISEamCyMKQApAOdspAJUYSc66FBMpTpV2MpLpBYLRdysPYMSS/bizYVm80TU4vv7hSS4QjOQr5WwLMpKvjy6MKAApAOVspwBUYiQ561JMpDhV2slIphcIRt8uj8LIZVG4q1FZvNaFAlC+KsFnEYg8Cj4qqUesCyMKQApApXsxOjo2S39dbhQlSIIzGcl0ycgZjEYvi8Ko5VHo0bgcXulcUx6UwyyYR/IFIaPQYUQBSAEoZztnAJUYSc4suBIhvrwvEwoMo2+W7seYFQdwb5MI/OfGGlaG5Sgb3mvy5SCj0GFEAUgBKGc7BaASI8mZBVciFBhxI4/C2RaByKOvl+zD2JUH0bNpBAZ3ogB0dkbYG10g8sjeyJzjpQsjCkAKQKW7io+AlfCZzroUE3USmfdARjLdQDD6avE+jFt1EA9cVx4v3lBdHpTDLALByGEhez0cMpKR6cKIApACUM52zgAqPBdP6QAAIABJREFUMZKcdSkmUpwq7WQk0wsEoy8X7cX41YfQq1l5vNCRAlC+KsFnEYg8Cj4qqUesCyMKQApApXuRM4BK+DgDaBGfLgXXYri2zALBaOjCvZiw9hAebl4Bz3WoZmuc2ekUCEbZGZ8vzk1GMkVdGFEAUgDK2c4ZQCVGkrMuxUSKU6WdjGR6gWDk+hQcVwHL1yNYLQKRR8HKxjVuXRhRAFIAKt2LnAFUwscZQIv4dCm4FsO1ZeZvRheuJKDjl8vMsf335lq4rX5ZW+PMTid/M8rO2Hx1bjKSSerCiAKQAlDOds4AKjGSnHUpJlKcKu1kJNPzN6MzF+PR5evl5kCWDWyP3GE55UE5zMLfjBwWrq3hkJGMTRdGFIAUgHK2UwAqMZKcdSkmUpwq7WQk0/M3o+jzcbh15EqE5QBWvHi9PCAHWvibkQND9npIZCQj04URBSAFoJztFIBKjCRnXYqJFKdKOxnJ9PzFaN/JizA+AXdr/TIY+Ntm5M2VE0ueby8PyIEW/mLkwFBtD4mMZHS6MKIApACUs50CUImR5KxLMZHiVGknI5mevxjd9PVynLoY7x5AobxhWPBsO3lADrTwFyMHhmp7SGQko9OFEQUgBaCc7RSASowkZ12KiRSnSjsZyfT8xci18tc1guL5c2PO023kATnQwl+MHBiq7SGRkYxOF0YUgBSAcrZTACoxkpx1KSZSnCrtZCTT8wcj4/HvfePWpDp50Xy5MPeZtvKAHGjhD0YODFNpSGQk49OFEQUgBaCc7RSASowkZ12KiRSnSjsZyfR8zWjLsVj0nrA+wxOvHsRFIPIVCU4LX+dRcFLIetS6MKIApABUuj+5D6ASPtNZl2KiTiLzHshIputLRlcSktDuiyWZnpQCUL4ewWrhyzwKVgbSuHVhRAFIASjlepbtFIBK+CgALeLTpeBaDNeWmS8ZHT57Cd2/XU0BaOtKBLeTL/MouEno//+QUgBSACrdoxSASvgoAC3i44+SDMqXjP7ZHYPB07a6T9qndSV8u+KA+d8dqpfEp93rywNyoIUvGTkwPJ8MiYxkjLowogCkAJSzPQsLCkAlfBSAFvHpUnAthmvLzJeMOn65FBeuJJrjuLNhWQyIrIrOI1K+AvJG15q4s2E5W2PMbidfMsruWPx1fjKSyerCiAKQAlDOdgpAJUaSsy7FRIpTpZ2MZHq+ZOS59Yvrs29v/LkN246fx+THmiOHcbIgPHzJKAjDtzRkMpIx6cKIApACUM52CkAlRpKzLsVEilOlnYxker5k1O+XjVh/6CzeuqkWbm9QVj55kFj4klGQhOz1MMlIRqYLIwpACkA52ykAlRhJzroUEylOlXYykun5kpFrBnB4j4ZoVaW4fPIgsfAloyAJ2ethkpGMTBdGFIAUgHK2UwAqMZKcdSkmUpwq7WQk07PC6LuVB7DlaCze71YH+XKHZdjpmYvx6PJ1yvt+39zXCM0qFpNPHiQWVhgFSSh+GyYZyWh1YUQBSAEoZzsFoBIjyVmXYiLFqdJORjI9idGJ2Dh0G7XS7OjrexuheaWMhd2Mzcfw7l87TTvjfb/KJQrIJw8SC4lRkITh12GSkYxXF0YUgBSAcrZTACoxkpx1KSZSnCrtZCTTkxjtjrmAB75fa3b06Z310KFGOIzyl3ZBh+cCkGDd8DkzWhIjmbL+FmQkX2NdGFEAUgDK2U4BqMRIctalmEhxqrSTkUxPYrTteCwe+THl027v3FIbaw+ewfTNx9PN8rkEYETRfJjWp6V84iCykBgFUSh+GyoZyWh1YUQBSAEoZzsFoBIjyVmXYiLFqdJORjI9idG/R87hiYkbMuzINdNnlMOWny82bYbcVR/tq5WUTxxEFhKjIArFb0MlIxmtLowoACkA5WynAFRiJDnrUkykOFXayUimJzEyZvye+vXfLAXgT2sPYcjCvabNxEeaoUapgvKJg8hCYhREofhtqGQko9WFEQUgBaCc7RSASowkZ12KiRSnSjsZyfQkRiv2n8KAKZsz7GjWk61w8kI8Hvpxnbvd+Ft4obzyiYPIQmIURKH4bahkJKPVhREFIAWgnO0UgEqMJGddiokUp0o7Gcn0JEaL9pzEoN+3ZNhR0Xy5cPZyQqq2VS9GBu0XPzKjJTGSKetvQUbyNdaFEQUgBaCc7RSASowkZ12KiRSnSjsZyfQkRveNW4N9Jy+m6igj4ecy0G0FsBGXxEimrL8FGcnXWBdGFIAUgHK2UwAqMZKcdSkmUpwq7WQk05MYeW7vYvT2eff62HwsFmNXHMiwcwpAmbmOFlIe6RiztzHpwogCkALQ29xPZR8dHZulvy43ihIkwZmMZLpkpM6oy4jlOHMpHv3bVUHt0oXQrloJTN90DO/NSdn02fN4tGVFPBtZVT5pkFkwj+QLRkahw4gCkAJQznbOACoxkpxZcCVCfHQnE5IZdRq+DLFxCZjUuzmqlEz5usdf207gjZnbU3VfPbwAfn60uZVTBp0N7zX5kpFR6DCiAKQAlLOdAlCJkeTMgisRksWN3IP+FlIetRmyGAlJyZjRtyXKFslnArmSkIR7vluNo+fi3IAqFsuH357QawNoV3ASI/2zRI6QjEKHEQUgBaCc7RSASowkZxZciRAFoEwoa0YJiUloM3SJ2c3cp9ugaP7cqbqMT0xC7wnrsTP6gpYbQFMAWsmgFBvWI5mVLowoACkA5WynAFRiJDnrUkykOFXayUim58koKSkZe2IuonKJ/MgdlhPR5+Nw68iVyJkDWPp8e+QKy5muQ6MUGlvBFEsjDuUzB48F80i+VmQUOowoACkA5WynAFRiJDmz4EqEOCshE0rNaMbmY3hn9k50q1cab99SBxsOnUXfXzYiokheTOvbykp3WtrwXpMvKxmFDiMKQApAOdspAJUYSc4suBIhCkCZUGpGd49ZjQOnL5luxnYuri1gyhfNh9/76Pl+n7eMkpOteISeDeuRfM11YUQBSAEoZzsFoBIjyVmXYiLFqdKuM6O5O6IxbfMxvHtLbRQvkMc2Jk9G949bi90xF9IJQJcgtH2SIHfUOY98dWnISCapCyMKQApAOdspAJUYSc66FBMpTpX2YGd0Pi7B/ApHg3KFsTLqNN6fswuvd62JNlVKuGfnbq9fBm/dXNs2Jk9Gd4xehSNnL5t9jX2gCR6fuMHdr44bPFuFFux5ZDVOFTsykunpwogCkAJQznYKQCVGkrMuxUSKU6U92Bk9OH6tucL29S418cHfu0wUhfKG4Y9+rdDxy2VuNOMfaoq6ZQrbQuXJqPNXKZs+pz3ubFAWb9xUy1b/OjgFex4F4hqQkUxZF0YUgBSAcrZTACoxkpx1KSZSnCrtwc4o7WfYXAJwYIdq5myg66hcPD8mP97CFipPRjd/vQIxF66k62dO/9ZKj5ltDcxBTsGeR4FASUYyZV0YUQBSAMrZTgGoxEhy1qWYSHGqtAc7o4wEYFgO4Ml2VTBiyf5UaOw+onUxOn7iHFp9vjhD3Hb7Vrl2TvIN9jwKBEsykinrwogCkAJQznYKQCVGkrMuxUSKU6U92BllJAAz4hFRNB+m2Vyl62L0w6LdeHPmjnTd92hcDq90rqlyGYLeN9jzKBAXgIxkyrowogCkAJSznQJQiZHkrEsxkeJUaQ92RlYF4EPNK+D5DtVsoXIxen3SBkxYe9jsY/ZTrc1FJ4lJyehSuxTy5Q6z1bcuTsGeR4G4DmQkU9aFEQUgBaCc7RSASowkZ12KiRSnSnswMzJKTMtMHsm6mBjv/kWdvoSHm1fAczYFYGJyMj6YtwczNh4xu328dSX0b1dFBbt2vsGcR4G6GGQkk9aFEQUgBaCc7RSASowkZ12KiRSnSnswMzp3OR43frU80/B/frQZZm07ge9XHTRtbq1XGi90rO71J9k2HD6Lvj9vdJ/n3Vtr45a6ZVSwa+cbzHkUqItBRjJpXRhRAFIAytlOAajESHLWpZhIcaq0O53RnpgL+M/0rWhZqRheTvOe3amLV3DT1yvShV80Xy60r1bC/FTbN0v3Y8yKA6lsljzfHnlzpf9mb9qOjBJmiEejj0SPr1uM6tkYTSsUVcGuna/T88gJwMlIvgq6MKIApACUs50CUImR5KxLMZHiVGl3OqMvF+3F+NWHzBBXvBCJsJw53OHuij6PXuPXmf9dqXh+3FK3NBpGFEGzCkVNuxw5cmDMiih8szQqFaJP7qiHjjXDU/1t+f5TePPP7YisXhKvdamJ3GE5sXTvKQycujkd3uUvRCKXxzhU+Ovi6/Q8cgJnMpKvgi6MKAApAOVspwBUYiQ561JMpDhV2p3O6JN5u/HrhpR37/7q3xolPD7p9t3KA+6tXhY/1y7DhRhvz96BP7ccT4Xolc410KNxRKq/vTpjG+bujDb/9mjLijC+7fu/qxtLexpyxW/G2eb0PFK5R3zlS0YySV0YUQBSAMrZTgGoxEhy1qWYSHGqtDudkacwm/hIM9QoVdAd7pCFe/DT2sPo2TQCgzvVyBBD56+W4ezlhFRtz7Svgt6tKqX62yM/rsO24+ezRLl6UCSAazOQKtx183V6HjmBNxnJV0EXRhSAFIBytlMAKjGSnHUpJlKcKu1OZ3TfuDXmt36NY/g9DdGqcnF3uJ/O341f1h/B460qon/7qhli2HL0HHr/dO17vYZR7rAc6FC9JF7vWgsF84QhKRloPSTjDZ4Ne+Px8oznIhF/4TKSPd4FVOGum6/T88gJvMlIvgq6MKIApACUs50CUImR5KxLMZHiVGl3MqNDZy7hrjGr3eE1LFcYo+9v4n4P8KO5uzBl41H0a1MZfdtWzhSDa6/Ae5tEYNLVx8ku4xtrheOexhHoP+nfDP3fvKkW7mxYFuHhhRETE0sBmAllJ+eRyv3hS18ykmnqwogCkAJQznYKQCVGkrMuxUSKU6XdyYwy2uT50zvro0ONkmbI78/ZiWmbjuHp9lXwWJpHup5Mjpy9jH2nLqJ6yQK4ffSqLHH99ngL3D32mug0PvHmZEYq196XvmQk0ySj0GFEAUgBKGc7BaASI8mZBVciBEeLm4wEYLd6pc0ZwOmbry3sGBBZFY+0rCgGez4uATcMX5alnSH4Xp2xFXN3xmB4j4ZoVaW4oxmJQQfIgPeaDJqMQocRBSAFoJztFIBKjCRnFlyJUPYJwKTkZCzecxL1yhZGqUJ50w00ISkZbbJ4L8/T4YNuddC1Tmk5WADD/tmLS/GJGNixOkYvj3JvEm04/9mvFUoXzou4hCQcPnsJ1UqmLDhhHsloyYiMZAKyhS55RAFIAShnOwWgEiPJWZdiIsWp0p5djGZtO463Zu5A/tw5sei59ulCOHspHp1HpHzlo2ONkli4+2SmYabdH9Aqj2PnLqd6JGzM/mV0ZBcjq3E4wY6M5KtARqHDiAKQAlDOdgpAJUaSMwuuRCj7Zrfenb0DM67uz5dWeBmzg58v2GOu8DUOY/+/o+fi0HvC+nQB9W1TCf3a2v8u78ytxzFs0T7858Ya6JRmc2jXyZhHzs0jeWTOsWAeyddCF0YUgBSAcrZTACoxkpx1KSZSnCrt2cVo/KqD+HLxPnPoaff323osFo96iD2XQFyy9yRemLoF5YrkxefdG2Dr8VjcWq+M37/KkV2MVK5roH3JSCZORqHDiAKQAlDOdgpAJUaSMwuuRCj7ZgB///coPrj6pY2G5YpgbK8m7sGu2H8KA6Zc+wSb5wzh8dg48zu+xfLnloPzkQXzSAZJRmQkE5AtdMkjCkAKQDnbKQCVGEnOuhQTKU6V9uxiNHnDEXw8b7c59NaVi+PLexrCKBn/nbUDs7adcId0Q81w/N8d9VRCVPbNLkbKAw9gB2Qkwyaj0GFEAUgBKGc7BaASI8mZBVcilH0zgD+vO4zPFuwxB/hSp+owNmkeMGUTVkadSTXofwa0Q4E8YXIgfrRgHslwyYiMZAKyhS55RAFIAShnOwWgEiPJWZdiIsWp0p5djH5ccwhf/LPXHPrADtXMrVaGLEz5b9fRtmpxfHF3Q5XwfOKbXYx8MvgAdUJGMmgyCh1GFIAUgHK2UwAqMZKcWXAlQtk3Azhu5QF8tWS/OUDjSx4jrv7bc8TtqpbA0LsbyEH42YJ5JAMmIzKSCcgWuuQRBSAFoJztFIBKjCRnXYqJFKdKe3Yx+nZ5FEYuizKHbmzlMnr5gXRh5MqZA8tfiFQJzye+2cXIJ4MPUCdkJIMmo9BhRAFIAShnOwWgEiPJmQVXIpR9M4DfLN2PMStSRN+jLSum+iKH56gz25xZjsx3FswjmSUZkZFMQLbQJY8oACkA5WynAFRiJDnrUkykOFXas4vR8MX73KIvB4Dkq0HUKV0I20+cd4dEAahydQPnm115FLgI1c9ERjJDXRhRAFIAytlOAajESHLWpZhIcaq0ZxejoQv3YsLaQ+mG/vHtdfHyjG3m3z++o16mX+dQidlb3+xi5O04s9OejGT6ZBQ6jCgAKQDlbKcAVGIkObPgSoSy5xFwfGIS2g5dkm5w4QXzmBtC3zF6ldnmhNk/YxzMI2fmkTwqZ1kwj+TroQsjCkAKQDnbKQCVGEnOuhQTKU6V9uxgNGHNIQy9ugWM59jvv648Bt1QHSujTptf+qhdupBKaD7zzQ5GPht8gDoiIxk0GYUOIwpACkA52ykAlRhJziy4EqHsmd36z/StWLArJt3g2lQpjmE9sn/fv7QDYx45M4/kUTnLgnkkXw9dGFEAUgDK2U4BqMRIctalmEhxqrRLjIzbOCkZCMtpLNVQP3ZHX8AD49dm2FGDcoXxXa+m6ifxcQ8SIx+fLii7IyP5spFR6DCiAKQAlLOdAlCJkeTMgisRujYD+Mbkjdhx4jy+uLsBcoflNB1jzsfhlpErzX8vfq4d8uVW/yTb7aNW4lhsnHtgEx9phrdmbceu6AvmF0EebF5BHnSALZhHMnAyIiOZgGyhSx5RAFIAytlOAajESHLWpZhIcaq0G4xKlCiEaq/NNLv55I566FgzHJ7f6nX174tFGS0+W5RquEafx2PjsOHQWXSpUwo5jQE57GAeyReEjMhIJiBb6JJHFIAUgHK2UwAqMZKcdSkmUpwq7QajQdO34Z+d0WY3r3Wpie4Ny6Ll54vTdTunf2sUL5BH5XTwFICjezZGkwpFlfoLhDPzSKZMRmQkE5AtdMkjCkAKQDnbKQCVGEnOuhQTKU6VdoNR809Tz8p9dU9DPDN5U7puXYs0jFs7h82Zup7j1mDvyYtm376YUVSJ3aov80gmRUZkJBOQLXTJIwpACkA52ykAlRhJzroUEylOlfaMBGBW/X14W118tmAP+revgjsalPX61C9N24KFu0/i5Rtr4J4mEV77Z4cD80imTkZkJBOQLXTJIwpACkA52ykAlRhJzroUEylOlfa4hES0/2KprS7szOA9O/lfrIw6g//eXAu31fdeQNoaqKIT80gGSEZkJBOQLXTJIwpACkA52ykAlRhJzroUEylOlfaNR86iz8SNGXYxvW9LfL5gjzljl9HhrQA0SkKXEctx9nICguX9PyNu5pGcYWRERjIB2UKXPKIApACUs50CUImR5KxLMZHiVGn/ae0hDFm4F2UL58Wkx5ojcljKbGCl4vkx5fEW5r9f+2Mb/t6RskjE85j1ZCuEF8qb7u9bjsWi94T15pc8vn+wqXsPwYOnL+HusatN+0XPtUN+H2wroxK7VV/mkUyKjMhIJiBb6JJHFIAUgHK2UwAqMZKcdSkmUpx2242tV/r+kjL790Cz8nixY3UYj2h3x1w09wN0fYotMwH4Qbc66FqndLrTe670NUSkISaNw/Pv3s4e2o3RF37MI5kiGZGRTEC20CWPKAApAOVspwBUYiQ561JMriQk4fSleJQpnH62TWKQVfuNXy3DucsJpsnT7avgsVaVYNy28YnJyJMrZTNo4/h0/m78sv5Iuq5e6VwD3RuWw7BFe81v97r8PbeQ+fb+xmhcvihcs4KuTigAVa6c83x1udf8SZaMZLq6MKIApACUs50CUImR5KxLMen38wasP3wOxlczapQqiMvxieZ7eU3KF8Hto1chomg+TOvTUsKRrt1zRu69W2vj5rplMuzj3OV4PDt5E7YdP5+u3ZgFfP3P7ebff+3dHEXy5cLN36xw2310e13cWKtUqtk/o5EC0OvL5WgHXe41f0ImI5muLowoACkA5WynAFRiJDnrUkxcQq1lpWL46t5GiPxiCS4nJKUKf/nA9sh19RNuWXHZd/Iiluw9iZ5Ny6PdF0vcpmN7NUHDckUkpOj3y0asP3Q2Q7sXb6iO8IJ5zHcGPY+lz7dPda4ba4Xjo9vriedyioEueeRPnmQk0yWj0GFEAUgBKGc7BaASI8nZiQU3LiEJYTlgSay54vOcqTNElrEyN+0x5K76KFskH6qXLIBvlu43P6nWt21l8383Hz2HAnnCUK1kQbT6fBGSktOTs/qVj3+PnMMTEzdkir5ovlzmKl/P482bauG9v3aafzK+MvJSpxqpHjFL1zG7252YR9nNJO35yUi+ImQUOowoACkA5WynAFRiJDk7reAePnsJ3b9NWQU766nW5myZdCQmJaP1kPSfZcvM76VO1fHJ/BSB+ELHauhQo6T7nMbK2+uvrvJN6796UKSx4Yk0HPMdwTdnbjeF5axtJ0R7w6BV5WLm3n+5w3Jg2UDjPMF1OC2PnEiPjOSrQkahw4gCkAJQznYKQCVGkrOTCm58YhJemrYVS/edModdtWQB85056dgdcwEPfL82Q7Prq5fEoj0Z79Hncnjrplp49+rsW8Vi+XDwzOV0fc0eGInwXDmQnMHMoDS+jYfP4nhsnPs9QJf9m11r4b05KbN+rmNAZFU80rKi1KXj2p2UR46Dc3VAZCRfGTIKHUYUgBSAcrZTACoxkpydVHAH/b4lnVizshDizy3H8fbsHRmGuvLFSLz/107M2HJcQpFl+/6PuiEmJtaWADQ6Nh5rt/d4n9D42/IXInH9sCXmimLXMfTuBmhXtYTSWLPD2Ul5lB3xWzknGcmUyCh0GFEAUgDK2U4BqMRIcnZSwfV8j88Yd56wHFj8fHvzUWpWx9K9pzBw6uYMTQwBmZCUjDZePCJO25Gx+KNTo/JKAtDo0zO+Pq0r4cl2VbAy6rS5eth1zHumDYrkyy1dNse1OymPHAfn6oDISL4yZBQ6jCgAKQDlbKcAVGIkOTul4HqKtLsalcUfW46bM2M31SmFt2+uneWCkL4/b8CGw+fShVqrVEFMeKSZ+feV+09j9cEzuL9pBPr8vBE31y2NMSsOZIpnwbNt8d3KgyhbJC/uaxqB8PDCygLwh9UHsffkRbzRtZb7yx9GCRi2aB9OxMbh1S41UShvLumSObLdKXnkSDgUgJYvC/NIRqULIwpACkA52ykAlRhJzk4pJjEXruCWb1YgZw6YiyAe/GEt9sRcNIffpkpxvNy5BsoXTflaRtrjztErceRcHCoXz4/+7avglRnbMPSuBmhbtThyZDF7uOP4eTz04zqzuxIFcuPUxXjz38bCkF7NKrhP4xRG0rXMznYykumTERnJBGQLXfKIApACUM52CkAlRpKzE4rJr+uP4JP5u91C7K/+bfDqjG2YuzP1t3W/69UEv286ht4tK6JCsWti8N7vVmP/qUv45r5GaFaxmBRyqvaFu2LML3AYwnH2thPYcjTl354zcU5g5FVQ2WBMRjJ0MiIjmYBsoUseUQBSAMrZTgGoxEhyzu5icj4uATcMX+YeZofqJfFp9/qZflrNMMybKyeWPN/e7eN6t27MA03QKELeqFlikrY9uxl5O97ssCcjmToZkZFMQLbQJY8oACkA5WynAFRiJDlnRzGZtzMay/edxjORVXDmUgLuG7fGPczhPRqiVZXiOHD6Eh7/aX26DZNdhsY7esYsnefqWtcn1aSYvW3PDkbejjG77clIvgJkREYyAdlClzyiAKQAlLOdAlCJkeScWTFZFXUaqw6cwVNtK3v1RQ7pfGcuxaPLiOWmmbG29/kO1TD0n73mfxt74D3cokKq9/aOnbuMb5ZFwdjqxfP48aHrULtMIRjf4L3xq5T+7DwClsZrjjMHfLIIxMq5gtWGjOQrR0ZkJBOQLXTJIwpACkA52ykAlRhJzpkVE9dj1ZdvrIF7mkRI3VhuN2b2eoxN+dJH2iOrPf/SbhEzqmdjNK1QFFuOnkPvn1I+u7bqxcgsF31YHmQaQ10Krt34rfiRkUyJjMhIJiBb6JJHFIAUgHK2UwAqMZKcJQH4UPMK5iydr47MvtpRulAe/Plk60xP8/WSfRi78qC73RCmdcsUMv/m+tKHlU2j7cShS8G1E7tVHzKSSZERGckEZAtd8ogCkAJQznYKQCVGknOgBeDWY7F4dML6dMOa/0xbFM4n74GXdibQ1ZExG2jMCvrj0KXg+oONq08ykumSERnJBGQLXfKIApACUM52CkAlRpJzoAXgpiPn8PjElEe2TcsXwUMtKiKyWgnLj24zE4BGf5wBlK62/9p1+VHyHyG+S2qFLfNIpqQLIwpACkA52ykAlRhJzoEWgBsPnzW/xFGhWD5MfaKlNLx07VGnLuKe766tGnYZtK5SHF/2aOh1f1YcdCm4VmK1a0NGMjkyIiOZgGyhSx5RAFIAytlOAajESHIOtADccOgs+v6yERWL5cNvNgSgEU9Gs4CznmyF8EJ5pXBttetScG0Fb9GJjGRQZERGMgHZQpc8ogCkAJSznQJQiZHkHGgBuP7QWfT7ZSMqFc+PKY+3kIaXYftDP6zDjhPnzbbGEUUw6v7GyGkE4qdDl4LrJzxmt2Qk0yUjMpIJyBa65BEFIAWgnO0UgEqMJOdAC8C1B8/gqV//RZUS+THpMXsCcNvxWDzyY8pCkv/dVhddapeSwlRq16XgKkEQnMlIpktGZCQTkC10ySMKQApAOdspAJUYSc6BFoBe+9MTAAAgAElEQVRrDpxB/0n/omqJAvj1sebS8DJsN26bV2Zsw75TF2F8H7hgHnn1sK0TXXXSpeCqMJB8yUgixFlSmRAZhRIjCkAKQCv5nqlNdHRslv78UZLxBloArj5wGk9P2oRqJQvgl972BKAclW8tmEcyTzIiI5mAbME8Ch1GFIAUgHK2cwZQiZHkHGgBuDLqNJ6dvAk1wgti4qPNpOE5op0/SvJlICMykgnIFsyj0GFEAUgBKGc7BaASI8k54AJw/2k8O2UTapYqiJ8eoQCUrk+wtPOHW75SZERGMgHZQpc8ogCkAJSznQLQEqMzl+Jx9lI8KpcoYMneZRRoAbh8/yk8N2UzapUqiAkUgF5dKycb6/Kj5E/GZCTTJaPQYUQBSAEoZ3uICMAdx88jCcmoW6awLSbthi7GlcRkTH2iBSoUy2+5j0ALwKX7TmHgb5tRp3Qh/PDwdZbHmZ2G/FGS6ZMRGckEZAvmUegwogCkAJSzXXMBaKTA1E3H8OHfu8xIFzzbFoXyer+q1XNz5N8eb4GKxa2JQEkAPtisAgZ2rKZ0nTydl+49hYFTN6NumUIY/xAFoM/AZnNH/OGWLwAZkZFMQLbQJY8oACkA5WzXXAC+NXM7Zm074Y5y4iPNUKNUQa+5pP06htXv4gZaAC7ecxIv/r4F9coWxvcPNvU6zuxw0KXg+pMdGcl0yYiMZAKyhS55RAFIAShnuyYC8OKVRBw8fQkxF66gVumCKHX1s2VphZshigxx5O3hLwH4UPMKeL6D72YA/9l9EoOnbUH9soUxjgLQ28vsWHtdfpT8CZiMZLpkFDqMKAApAOVs10QA/t+83Zi04Yg7mjn9W6N4gTx4etK/WH3gjPvvAztUw4PNK3jNxVMAevOZNWkG0PcCMAaDp21Fw3KFMbYXZwC9vtAOdeAPt3xhyIiMZAKyhS55RAFIAShnuyYCMO0MnRHWS52q45P5e9JFaPXxrcvRSKOWny9O1c/QuxqgXbUSIt9AC8AFu2Lwn+lb0SiiCMY80EQcnxMMdCm4/mRJRjJdMiIjmYBsoUseUQBSAMrZrokAvGP0Shw9F2cpXm8FYHxiEtoOXZKq7xIFcuOv/m3E8wVaAM7fFYOXp29F44gi+JYCULw+wWKgy4+SP3mTkUyXjEKHEQUgBaCc7ZoIwHvGrkbU6UuW4vVWABpbyDz04zpbM4mSAPT1KuB5O6PN7/g2LV8Eo+7nDKClhAgCI/5wyxeJjMhIJiBb6JJHFIAUgHK2ayIAe41fi13RFyzFO+Hh61A9vCDCcuawZH/LNyvMxSVpD0NIGrODJ87HoXzRjLeFCbQA/HtHNF77Yxuuq1AUI3s2thRfdhvpUnD9yZGMZLpkREYyAdlClzyiAKQAlLNdEwH4yI/rsO34ecvxPhtZFY+2rGjJ/v/buxd4m8r8j+M/nBySO6GERLqgi1uZKJcyo1JRmRpKoaRMJUkXJZlmJJQuf0q6CUORmaarIuSupDKY5LjkfsklOeXyf/2eYx97n9tv77OtLGt91us1r6n2s9ZZ+72e/ezvftbzPCun8YW64+VnnSj/WZKxxMzw6+tKvVNKuX/+bsMuWb19j/zpzApiBcAjPQlEJ8LohJh6p5SU4dcTAOO6wMdAoaB8KXlJjZGti1F4jAiABMBstf3KK6+UUqUygsr5558v9957b66fiM2bd+X5afFTY9Jl7CL5et1O+9N9qIR2/s3t2TSu8tEBUJeRufmtr7Ltd2mt8lKySIq8/fX6zNfuvSRjxnG5csVly5ZdcvDg4d0ixzzSATBy3Mqlisikzg3jen9Hu5Cf6tHRtsjt72NkXxmMMLIF7BJBqUcEQAJgTG3fvXu3dOvWTUaPHm1/CkTkaATAVdv2SIXiqVLkuEJxnWOkUE4B8IJqpWXdjr3S8vRyMmrumpjjJbJMSnQA1Nu+l744W/TZwPFsC3o1PSoBUM8t0bGO8bwfL8oEpcH1wiZyTIxsXYwwsgXsEkGpRwRAAmBMbZ83b570799fypQpI6mpqfLwww9LtWrVcv1E/J4BMDJ2LXIyn93ZWNbt3Cs1yxeTgvqJNLZbxyySb9bvFJ1UMfX7LXJfs9Ok6WllM/fKehv3vMol5aU4xsit3v6LtBs1P/M4GqpyuyWc0ylO69FYSpUuJq9PXyGtzjhRyhYr7IpFjnGkJ4FkDauWmx9eD0qD66UlRrYuRhjZAnaJoNQjAiABMKa2L1myRJYuXSrXXHONfPnllzJo0CAZN26cLwJgXpM45vVsIgWMEHjLmK/k2/W7ZPDVZ8cEv8ibyxra4n1U2n++2yj9PlwWEwA1EGow1E2D5uCpsWsNPnJZTRnwccazh3VLTSko6fsOxDydI3I+7c87SXo1r2G3SnGWIADGCXWMFQvKl5KX7BjZuhiFx4gASACMqe3p6ekuSBUunNEL1bx5c/nss898EQDzmsSRW6j75bf98tXaHdKgSinpPHaRmwQy9Jqz5aLqh3v+Im+uxQuzZOfefVKogMj+gyKnlTteBrU5W0oVPU6KF0nJ1WD6iq1y37vfxQRADX8Pv/dfuanhKVK4UAH35I3obfa9TeTCobELR0den9L9QilZ9LiYXsQJnepLtbLH2y1THCUIgHEgHYNF+OK2LxpGGNkCdomg1CMCIAEwpra/9tprsmnTJundu7dob+CTTz6Z53hAr28B6zi6SYvXy+VnVZA+/14i36zfJbrA8rY92cfXtTy9vKSmxN4KjszAvbHeybJwzQ5Ztmm3PNu2tjQ+NfsTOjS0vbt4vdQ5qYR7Ukb0preZdWmYnHoZF675SbqNXxwTAKP3PXDwoLw4M01en5cxxjDSs/j1jzuky7ivs7U2NcoVk7E314sJgEdy0WYCoN3AH4slgvKl5KU9RrYuRuExIgASAGNq+969e+X++++Xbdu2SaFChaRfv35SvXr1370HcPuejDX1hn+xSiYuXi8nlUiVYqkpbh2/59rVljlpP8lbC9dKscKF5Odf99ufWBE5uWQR+XHHXhn553PknJNL5rrPhp175cqX52V7fVLnBlK5VPa1/KwAGDnQd+t3ysfLNkvXC6vKCakZPYort+6RD5dulFFzYiegXFWnokz+ZkPMOURP2NDbxUs37pLalUrEvVZh5GAEwLiqyzFXiC9u+5JhhJEtYJcISj0iAAY8AGqQa9++vQwYMEAaNWrkavbWrVulb9++ohM+NOS1adNGHnjgAUlJyf02Z24fCe0BzGvonb5Wtmxx2bo1domTvD5in3+/VXoduqUatSqKVCld1I2re6l9XTn/0Hp6i9bG9qL9tempmeezfPPP8sGhNfii/97bt+R9O1WrRIPB2W/P6q3jJlGTRiLHfOfrdfL3T753/9qwSil58fq6dgsSVSJidOcb8zPXDMzpADpbWLdfft0vd0/8Vr7U935BFel2Uc6TdDbtSpchU1fIhaeWEQ2UGlR3pe+TXu8e7t2MHDOhEz4KhfNTj47CaR7VP4mRzY8RRraAXSIo9UiXHwvzVuBggAPgwoULpU+fPrJ69Wp54403MgNgx44dpUKFCvLEE0/Ili1b5I477pCrr75aunTpknBd2L//gBQqVDDh/fLaYeGq7dLu/2blWmTynX+Qcw4FQC30+qw0eeK9JTKxe2OpWzlj/ULdVmzeLS0Gf57tOAsfaSllT0jN85xHzVwp/d9bIi/fVF/GzVstny7NWMx55d9bZ7sNXK3PfzKP9cezK8rwjvXy5aFPDKn58Ae57rt8wJ+kcEpBaTV0uizbeHj9xdkPNpdKh54ycuDAQdFbzimFCsorM1c6F930fXR9Y0G2Y6f94/J8nSs7IYAAAgggcCwLBDYATpo0SYYNG+Zu5+pCzpEAuGrVKrnssstk+vTpLgTq9v7777vZvlOnTk34WnrRA6gn8drcNfL8jJU5ns/kLg3k5BxuxWYtrOv7tcnhVu7cnk0Sum06ZuFaGTL1B3f4V288140RjN7qPz09818vrlHWzTJOZIv+Ndl9/GKZu+qnzN1PL19MtCdTtz+eWV4GXH6mRP+9SMFh7WrLxl3pbpzhcQULythO9eSyF2e7SS15bfQAJnKl/F02KL0SXipjZOtiFB4jegAD2gO4efNmKV26tLutW6tWrcwAOGXKFLe239y5czNr+bJly9xt4Pnz50uJErHhxvooeDUJ5N/fbpD+Hy3P9uf10Wz6iLZ4Np0B3HTYF9mKJrr48Zbd6fKnEYe9si45Ez2m7qLqZWToNbXjOb3MMtHjSdZs/0WueSVjTcFuf6gqnS+oGjMZ5Jm2teWeid+ax49+BF1ehRO1MP+wRwWCMubGIx53WIxsXYwwsgXsEkGpR4wBDGgAjK7C0QFw8uTJMnToUJk2bVpmEb1FfOmll8rnn38uFStWtGt/VAmvAuAXK7dlCzo3nH+y9Gx2WkLn13XcIln0Y+zj3/ITeqJD3uN/qiWtz8roPdWt+fOz3Ng63RqfWlqebVsnoXO0GpN+HyzNc2xgQn8sS+H8WCTz9/K7r2WU3+MGaT+M7KuJEUa2gF0iKPWIABiyAPjJJ5/II488kmMP4IIFC6R48cQGhXoVAJds2BXzPF29bRvP0z6yfnSz9t511kkTf8j9ySa5ffR1+ZgOb37pXr6gaml57trDIW/k7FUyYtaqHF+zmxK750araMMhOa8ZaB3/hNRCMrlLQ2nxwuxsRY/0AtPWuSTzelAa3GQMrH0xsoTsz5p9hOCXoB7Z1zgoRgTAkAXAtLQ0adWqlXzxxRdSrlw5V9N1DODAgQNdD2Cim1cBMHoplg71K8vdF+e+FI11znPTtsvKbXtEA4/1tJC8jqW3XrVn8pRSRWRi54aZRXXcXWS8Yv0qpeT/rkt8FrCOxdiyJfeZ0jrbues/Y9cMHH59Xal3Silp+cIs2ZHLWL/X/nKee7rI1SPnuSVwIpsucj26Yz1JKWg/Qs/y/T1eD0qD66UVRrYuRhjZAnaJoNQjAmDIAqBW7RtvvNHd6tVn/m7fvt3NAtZQ2KNHD7vmZynhVQDUP/OvbzZIiSIpcknNjKB6tLdlG3dLh9EZvYAz777IPb5Nt1fnrnYLPet28Wll5el8TAKxAqAeO6dHzrkAv2SjzFixVUofX1gmLFoXwxS5xTt/9XbpPuGbzNeuO/ck6d3iyD1ezutrE5QG10snjGxdjDCyBewSQalHBMAQBkBd+kXDn04EKViwoFsCplevXm5NwEQ3LwNgoufidfl9Bw5mPr7tvdsaSYXiGUvJvDJnlVuwWrd/d20oFUsUSehUEmlMhk5bIWMW/ih/v+JMaVmrfMzf0eVfNDTrYtnjF61zT0z56I4LM8vsTt8nzZ7PWF5nfKf6cuoRerRcQm82n4UTMcrnnzjmd8PIvoQYYWQL2CWCUo8IgCEIgHZ1zn+JMAVAVWr2/BeyO32/dKxfWd5csDYGrt05laRPy5oJYx7pxkSr9H+WbJRTyxwvZ1eKndW9/8BB+fnXfVKiyHEJn+fR3OFIGx3N9+LV38bIlsUII1vALhGUekQAJADatT2PEmELgK1HzJHNuzMeU5d1u/acSvKADwJgUhfUpzsHpcH1khcjWxcjjGwBu0RQ6hEBkABo13YCYKZAu1Hz3ePoctr0UXXv3NogYc+gNCYJv/EEdsDIxsIII1vALkE9Co8RAZAAaNd2AmCmwA2vL5Tvt2Q8mSPr1kCfA5zgDGA9Bg2uXQUxwsgWsEtQjzCyBewSQalHBEACoF3bCYCZAndOWCzzVh9+VFs0ja63d1LJxCaAEADjq35BaXDje7f5K4WR7YYRRraAXSIo9YgASAC0azsBMFMgesZvVpb8PlUjKI1JUhXJ2BkjWxcjjGwBuwT1KDxGBEACoF3bCYCZAtFLqUT+Y51KxeWCaqXltsaJP2GEHsD4qh9fSrYTRhjZAnYJ6lF4jAiABEC7thMAYwR0vb2f0/dLwYIiuqxKskuq0ODaVRAjjGwBuwT1CCNbwC4RlHpEACQA2rWdAJiUkbVzUBoT630m8zpGth5GGNkCdgnqUXiMCIAEQLu2EwCTMrJ2psG1hJgpbQthhFE8AnYZ2qPwGBEACYB2bScAJmVk7UyDawkRbmwhjDCKR8AuQ3sUHiMCIAHQru0EwKSMrJ1pcC0hwo0thBFG8QjYZWiPwmNEACQA2rWdAJiUkbUzDa4lRLixhTDCKB4BuwztUXiMCIAEQLu2EwCTMrJ2psG1hAg3thBGGMUjYJehPQqPEQGQAGjXdgJgUkbWzjS4lhDhxhbCCKN4BOwytEfhMSIAEgDt2k4ATMrI2pkG1xIi3NhCGGEUj4BdhvYoPEYEQAKgXdsJgEkZWTvT4FpChBtbCCOM4hGwy9AehceIAEgAtGs7ATApI2tnGlxLiHBjC2GEUTwCdhnao/AYEQAJgHZtJwAmZWTtTINrCRFubCGMMIpHwC5DexQeIwIgAdCu7QTApIysnWlwLSHCjS2EEUbxCNhlaI/CY0QAJADatZ0AmJSRtTMNriVEuLGFMMIoHgG7DO1ReIwIgARAu7ZTAgEEEEAAAQQQCJBAgYMEwABdTt4KAggggAACCCBgCxAAbSNKIIAAAggggAACgRIgAAbqcvJmEEAAAQQQQAABW4AAaBtRAgEEEEAAAQQQCJQAATBQl5M3gwACCCCAAAII2AIEQNso1xJffvml/Pzzz1K+fHk544wz5MCBA1KwYMEkjhi8Xb/77jtnUqFCBSlTpgxGOVziJUuWSKFCheTkk0+WE044AaMcjBYvXix79+6VihUrSpUqVUTnrhXQ9TrYMgW++eYb2bNnjzRq1Ej279/v6hRbrABttl0jaLNto6CUIADm40pu375d7r//ftEPSs2aNSUtLU3effddF3DYMgQ2b94sDzzwgKxcuVKqVavmgvKIESOkdOnSEB0S2LZtm/Ts2VO+//57F/40KD/xxBNSo0YNjA4JbNmyxdWj//3vf87lq6++khdffFEuvPBCjKIEdu3aJZ06dZL09HR577333CuE5MNAtNn2x4U22zYKWgkCYD6u6LPPPiurVq2SIUOGuL1//PFH9wXOliHw22+/yX333SclS5Z0gWbKlCnuS/vpp5+W6tWrw3RI4Mknn5QdO3bIwIEDXX16/vnnRXsDn3nmGffDIuybBhj9oVW0aFFXj/bt2yePPfaYM5o0aVLYeWLev9pceeWVsnXrVunatav7H72Ah4los/P+uNBmh7M5IQAmeN21J+v222+Xtm3buv9NmDBB5syZI6eddpo0btxYzj333ASPGLzi2iP6+OOPS+fOneWiiy5yweajjz6Su+++W84888zQh2UdKqC3M7t16yaXX365tG/fPrMStG7dWpo0aSJ33HGHlCpVKniVI853pOFPQ7H+kOjVq1dmj9+0adNk8ODBMmbMGClevHicRwt+sRUrVrjPV5s2beSf//yn89FhF2EflqLvX3tFNRDTZuf8OdDP2po1a9yPK9rs4LcV0e+QAGhc72+//VY2btwoVatWdbeg9Lbd9ddf73okZs2aJfqFpL+8582bJ//9739l6NCh0rBhw1DVoqxG69evlxtvvFFOOukk17CkpKS4IKjlfvrpJxk9erR7LUybhhmtR5G6oQ4dO3Z0QU9Dn/bgqJPevtOeUg3NtWvXDhORC3zRRhs2bJC77rrLBb5TTjkl8xb56tWr5eWXXw6VTeTNRhtF9/DpLXI16dChg+tRrlWrljz66KNu6EWxYsVCZZXTZ+26666T/v3702YfqglZjfRz9+c//5k2O1SfFBECYC4XXHtodOyRhrzzzjtP5s+fL3369HG9Ndorob+469evL4888kjmEfQLvVKlSvLUU0+FYvxNXkY6aP/tt99249u0NyKytWrVSlq0aCG9e/cOhVHkfeutTA3Gr776qhx33HHuP2t90jGS2mMTPV5Lf1A0a9bMjQ8M0ziu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mA0BBBDwuwAB0O9XiPNDAIGkBbKuA6i3bjX06TqArVu3dj13AwcOlEmTJsmBAwekcuXKcsUVV8jgwYNl+vTpUq5cOTdbeMKECdKpUye599573TIyGgBXrVolRYsWdeV79uwphQsXTvp8OQACCCDgtQAB0Gthjo8AAggggAACCPhMgADoswvC6SCAAAIIIIAAAl4LEAC9Fub4CCCAAAIIIICAzwQIgD67IJwOAggggAACCCDgtQAB0Gthjo8AAggggAACCPhMgADoswvC6SCAAAIIIIAAAl4LEAC9Fub4CCCAAAIIIICAzwQIgD67IJwOAggggAACCCDgtQAB0Gthjo8AAggggAACCPhMgADoswvC6SCAAAIIIIAAAl4LEAC9Fub4CCCAAAIIIICAzwQIgD67IJwOAggggAACCCDgtQAB0Gthjo8AAggggAACCPhMgADoswvC6SCAAAIIIIAAAl4LEAC9Fub4CCCAAAIIIICAzwQIgD67IJwOAggggAACCCDgtQAB0Gthjo8AAggggAACCPhMgADoswvC6SCAAAIIIIAAAl4LEAC9Fub4CCCAAAIIIICAzwQIgD67IJwOAggggAACCCDgtQAB0Gthjo8AAggggAACCPhMgADoswvC6SCAAAIIIIAAAl4LEAC9Fub4CCCAAAIIIICAzwQIgD67IJwOAggggAACCCDgtQAB0Gthjo8AAggggAACCPhMgADoswvC6SCAAAIIIIAAAl4LEAC9Fub4CCCAAAIIIICAzwQIgD67IJwOAggggAACCCDgtQAB0Gthjo8AAggggAACCPhMgADoswvC6SCAAAIIIIAAAl4LEAC9Fub4CCCAAAIIIICAzwQIgD67IJwOAggggAACCCDgtQAB0Gthjo8AAggggAACCPhMgADoswvC6SCAAAIIIIAAAl4LEAC9Fub4CCCAAAIIIICAzwQIgD67IJwOAggggAACCCDgtQAB0Gthjo8AAggggAACCPhMgADoswvC6SCAAAIIIIAAAl4LEAC9Fub4CCCAAAIIIICAzwQIgD67IJwOAggggAACCCDgtQAB0Gthjo8AAggggAACCPhMgADoswvC6SCAAAIIIIAAAl4LEAC9Fub4CCCAAAIIIICAzwQIgD67IJwOAggggAACCCDgtQAB0Gthjo8AAggggAACCPhMgADoswvC6SCAAAIIIIAAAl4LEAC9Fub4CCCAAAIIIICAzwQIgD67IJwOAggggAACCCDgtQAB0Gthjo8AAggggAACCPhMgADoswvC6SCAAAIIIIAAAl4LEAC9Fub4CCCAAAIIIICAzwT+H/rCzqfr0nOtAAAAAElFTkSuQmCC\" 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": 90,
"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,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAgAElEQVR4Xu2dCZDV1ZWHD5uC0oksUYkDowwKmghBVkcGRIEEGVkVFwSVoLKooKwuDCG4gKCssisGxFgiAhI0sqhRUy6AisRoGHQMTg0CDY4oaIktU+dm+klDo919+sK9933/qlSE986/3/vO7x2+vv/lldm/f/9+YYMABCAAAQhAAAIQyBoCZRDArOk1bxQCEIAABCAAAQg4AgggQYAABCAAAQhAAAJZRgABzLKG83YhAAEIQAACEIAAAkgGIAABCEAAAhCAQJYRQACzrOG8XQhAAAIQgAAEIIAAkgEIQAACEIAABCCQZQQQwCxrOG8XAhCAAAQgAAEIIIBkAAIQgAAEIAABCGQZAQQwyxrO24UABCAAAQhAAAIIIBmAAAQgAAEIQAACWUYAAcyyhvN2IQABCEAAAhCAAAJIBiAAAQhAAAIQgECWEUAAs6zhvF0IQAACEIAABCCAAJIBCEAAAhCAAAQgkGUEEMAsazhvFwIQgAAEIAABCCCAZAACEIAABCAAAQhkGQEEMMsaztuFAAQgAAEIQAACCCAZgAAEIAABCEAAAllGAAHMsobzdiEAAQhAAAIQgAACSAYgAAEIQAACEIBAlhFAALOs4bxdCEAAAhCAAAQggACSAQhAAAIQgAAEIJBlBBDALGs4bxcCEIAABCAAAQgggGQAAhCAAAQgAAEIZBkBBDDLGs7bhQAEIAABCEAAAgggGYAABCAAAQhAAAJZRgABzLKG83YhAAEIQAACEIAAAkgGIAABCEAAAhCAQJYRQACzrOG8XQhAAAIQgAAEIIAAkgEIQAACEIAABCCQZQQQwCxrOG8XAhCAAAQgAAEIIIBkAAIQgAAEIAABCGQZAQQwyxrO24UABCAAAQhAAAIIIBmAAAQgAAEIQAACWUYAAcyyhvN2IQABCEAAAhCAAAJIBiAAAQiIyP79+6VMmTKwgAAEIJAVBBDArGgzbxIC6RFYv369PPLII/Lmm2/K7t275cQTT5Rzzz1Xrr32WvmXf/mXYr1h3desWbNk9uzZru6///u/5cILL5R7771XunbtWqx98WQIQAACMRBAAGPoEq8RAhAoQEBF7YEHHpDzzjtPunTp4uTv73//u/z+97+XzZs3O3Hr0KFDkamNGDFC3njjDXn++eddzddffy1//etfpVatWlK1atUi74cnQgACEIiFAAIYS6d4nRCAgCPwwgsvSN++faV///4ycODAAlT27dsngwcPds956qmn5PTTTy8StYMFsEhFPAkCEIBAxAQQwIibx0uHQDYS6Natm+zZs0eeffbZQs/Z+/TTT6V169bSrl07ue+++6Ru3boycuRI2bhxo6xcuVIqVaokF110kQwZMkQqVqwoKn9LlizJoNTVw6ZNmx5yCPijjz5yq456uFh//tlnny2DBg2SRo0audr8w8aTJk1yr+3ll1+W8uXLu9dx++23y/HHH++e9+6777rX9Ze//EW+/fZbadCggdxyyy3u/9kgAAEIHCkCCOCRIs3PgQAEzAR27drlzvPr3bu3DB8+/LD709XB119/3cmaCuCPfvQjJ1g9e/aUDz74QFTSWrVqJVOnTpUtW7bIXXfd5Q75Tps2zR323bt3bwEB1MPK3bt3l3/+53+W66+/XipUqCDz58935x8+/PDDThjzBfDHP/6xqKS2bNlS3nnnHZk4caJcd911bmXyiy++kLZt20qzZs3k0ksvFV2xnDFjhntNumqZk5NjZsQOIAABCBSFAAJYFEo8BwIQCIKAruJdcskl8h//8R/So0ePw76mcePGOTHT8/pUzk499VRZsWKFW5HTTS8e0ZW+P/zhD+4w8cGHgA++CERX+l599VVZvXp1RtK++eYb+fd//3f350WLFmUEsGPHjjJ+/PjMa+vVq5foquTy5cvl7bfflssuu0wee+yxzMqhCujjjz/u5LRGjRpBcOZFQAAC6RNAANPvMe8QAskQ0BU1XTkbM2aMW5E73DZhwgSZM2eOWwXU1bYBAwbIzTffnHn61q1b5fzzz5ff/OY3csUVV/ygAP7rv/6rW9EbO3ZsgR+pK4gPPvigW2lUydMrhw+W02HDhrnH16xZ4w4dt2nTRvLy8qR9+/ZuFVJXNPWwNBsEIACBI0kAATyStPlZEICAicDOnTtFZUwvAtHz5g636cUhL730krz11lvuEPDo0aPl8ssvzzxdr/LVc/huvfVWueGGG35QAH/2s5+528voeYMHbnrVsUqk/iw9nFvYrWMOXl388MMP3WHfF1980d2+RuVPVw3vuOMOOfbYY018KIYABCBQVAIIYFFJ8TwIQCAIAnoIVcXpmWeeKfQiED3PTlf39H+6EqgCqLKo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OhFAE76kixn8CGBMASevfroF13C5IoAIoCmdCKAJX9LFDH4EMKaAk1c/3YJruFwRQATQlE4E0IQv6WIGPwIYU8DJq59uwTVcrgggAmhKJwJowpd0MYMfAYwp4OTVT7fgGi5XBBABNKUTATThS7qYwY8AxhRw8uqnW3ANlysCiACa0okAmvAlXczgRwBjCjh59dMtuIbLFQFEAE3pRABN+JIuZvAjgDEFnLz66RZcw+WKACKApnQigCZ8SRcz+BHAmAJOXv10C67hckUAEUBTOhFAE76kixn8CGBMASevfroF13C5IoAIoCmdCKAJX9LFDH4EMKaAk1c/3YJruFwRQATQlE4E0IQv6WIGPwIYU8DJq59uwTVcrgggAmhKJwJowpd0MYMfAYwp4OTVT7fgGi5XBBABNKUTATThS7qYwY8AxhRw8uqnW3ANlysCiACa0okAmvAlXczgRwBjCjh59dMtuIbLFQFEAE3pRABN+JIuZvAjgDEFnLz66RZcw+WKACKApnQigCZ8SRcz+BHAmAJOXv10C67hckUAEUBTOhFAE76kixn8CGBMASevfroF13C5IoAIoCmdCKAJX9LFDH4EMKaAk1c/3YJruFwRQATQlE4E0IQv6WIGPwIYU8DJq59uwTVcrgggAmhKJwJowpd0MYMfAYwp4OTVT7fgGi5XBBABNKUTATThS7qYwY8AxhRw8uqnW3ANlysCiACa0okAmvAlXczgRwBjCjh59dMtuIbLFQFEAE3pRABN+JIuZvAjgDEFnLz66RZcw+WKACKApnQigCZ8SRcz+BHAmAJOXv10C67hckUAEUBTOhFAE76kixn8CGBMASevfroF13C5IoAIoCmdCKAJX9LFDH4EMKaAk1c/3YJruFwRQATQlE4E0IQv6WIGPwIYU8DJq59uwTVcrgggAmhKJwJowpd0MYMfAYwp4OTVT7fgGi5XBBABNKUTATThS7qYwY8AxhRw8uqnW3ANlysCiACa0okAmvAlXczgRwBjCjh59dMtuIbLFQFEAE3pRABN+JIuZvAjgDEFnLz66RZcw+WKACKApnQigCZ8SRcz+BHAmAJOXv10C67hckUAIxfAXbt2yWWXXSZ33XWXNGvWzCVt1KhRsnjxYqlQoUImeSNGjHDP023OnDmyYMEC2b17t5x99tkyevRoqV27tnts7969MmbMGHn+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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": 91,
"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 828.14%\n",
"Daily Sharpe 0.83\n",
"Daily Sortino 1.50\n",
"CAGR 19.77%\n",
"Max Drawdown -27.39%\n",
"Calmar Ratio 0.72\n",
"\n",
"MTD -2.35%\n",
"3m -6.48%\n",
"6m -1.22%\n",
"YTD -8.70%\n",
"1Y 3.25%\n",
"3Y (ann.) 14.66%\n",
"5Y (ann.) 13.57%\n",
"10Y (ann.) 25.61%\n",
"Since Incep. (ann.) 19.77%\n",
"\n",
"Daily Sharpe 0.83\n",
"Daily Sortino 1.50\n",
"Daily Mean (ann.) 21.64%\n",
"Daily Vol (ann.) 26.02%\n",
"Daily Skew 2.04\n",
"Daily Kurt 56.50\n",
"Best Day 29.25%\n",
"Worst Day -23.18%\n",
"\n",
"Monthly Sharpe 0.91\n",
"Monthly Sortino 2.91\n",
"Monthly Mean (ann.) 21.87%\n",
"Monthly Vol (ann.) 24.12%\n",
"Monthly Skew 1.87\n",
"Monthly Kurt 5.21\n",
"Best Month 34.48%\n",
"Worst Month -12.28%\n",
"\n",
"Yearly Sharpe 0.81\n",
"Yearly Sortino 6.27\n",
"Yearly Mean 21.94%\n",
"Yearly Vol 26.92%\n",
"Yearly Skew 0.74\n",
"Yearly Kurt 0.28\n",
"Best Year 79.93%\n",
"Worst Year -8.70%\n",
"\n",
"Avg. Drawdown -4.29%\n",
"Avg. Drawdown Days 41.94\n",
"Avg. Up Month 6.08%\n",
"Avg. Down Month -3.06%\n",
"Win Year % 75.00%\n",
"Win 12m % 78.99%\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