python-pour-finance/10-Plateforme-Quantopian/.ipynb_checkpoints/03-First-Trading-Algorithm-...

678 lines
287 KiB
Plaintext
Raw Permalink Normal View History

2023-08-21 15:12:19 +00:00
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# First Trading Algorithm\n",
"## Pairs Trading\n",
"\n",
"Pairs trading is a strategy that uses two stocks that are highly correlated. We can then use the difference in price between the two stocks as signal if one moves out of correlation with the other. It is an older strategy that is used classically as a guide to beginning algorithmic trading. There is a fantastic full guide and write up on Investopedia you can find [here](http://www.investopedia.com/university/guide-pairs-trading/)! **I highly recommend reading the article in full before continuing, it is entertaining and informative!**\n",
"\n",
"\n",
"Let's create our first basic trading algorithm! This is an exercise in using quantopian, **NOT** a realistic representation of what a good algorithm is! Never use something as simple as this in the real world! This is an extremely simplified version of Pairs Trading, we won't be considering factors such as cointegration!"
]
},
{
"cell_type": "code",
"execution_count": 103,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline\n",
"\n",
"import quandl"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## United Airlines and American Airlines"
]
},
{
"cell_type": "code",
"execution_count": 104,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"start = '07-01-2015'\n",
"end = '07-01-2017'"
]
},
{
"cell_type": "code",
"execution_count": 105,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"united = quandl.get('WIKI/UAL',start_date=start,end_date=end)\n",
"american = quandl.get('WIKI/AAL',start_date=start,end_date=end)"
]
},
{
"cell_type": "code",
"execution_count": 106,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style>\n",
" .dataframe thead tr:only-child th {\n",
" text-align: right;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: left;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Open</th>\n",
" <th>High</th>\n",
" <th>Low</th>\n",
" <th>Close</th>\n",
" <th>Volume</th>\n",
" <th>Ex-Dividend</th>\n",
" <th>Split Ratio</th>\n",
" <th>Adj. Open</th>\n",
" <th>Adj. High</th>\n",
" <th>Adj. Low</th>\n",
" <th>Adj. Close</th>\n",
" <th>Adj. Volume</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",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2015-01-07</th>\n",
" <td>64.96</td>\n",
" <td>66.11</td>\n",
" <td>64.00</td>\n",
" <td>65.53</td>\n",
" <td>5133939.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>64.96</td>\n",
" <td>66.11</td>\n",
" <td>64.00</td>\n",
" <td>65.53</td>\n",
" <td>5133939.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2015-01-08</th>\n",
" <td>65.70</td>\n",
" <td>67.52</td>\n",
" <td>65.41</td>\n",
" <td>66.64</td>\n",
" <td>6889597.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>65.70</td>\n",
" <td>67.52</td>\n",
" <td>65.41</td>\n",
" <td>66.64</td>\n",
" <td>6889597.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2015-01-09</th>\n",
" <td>66.76</td>\n",
" <td>66.97</td>\n",
" <td>64.90</td>\n",
" <td>65.34</td>\n",
" <td>3488027.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>66.76</td>\n",
" <td>66.97</td>\n",
" <td>64.90</td>\n",
" <td>65.34</td>\n",
" <td>3488027.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2015-01-12</th>\n",
" <td>66.16</td>\n",
" <td>66.85</td>\n",
" <td>63.84</td>\n",
" <td>65.92</td>\n",
" <td>5246008.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>66.16</td>\n",
" <td>66.85</td>\n",
" <td>63.84</td>\n",
" <td>65.92</td>\n",
" <td>5246008.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2015-01-13</th>\n",
" <td>66.84</td>\n",
" <td>68.26</td>\n",
" <td>65.45</td>\n",
" <td>66.41</td>\n",
" <td>6265791.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>66.84</td>\n",
" <td>68.26</td>\n",
" <td>65.45</td>\n",
" <td>66.41</td>\n",
" <td>6265791.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Open High Low Close Volume Ex-Dividend Split Ratio \\\n",
"Date \n",
"2015-01-07 64.96 66.11 64.00 65.53 5133939.0 0.0 1.0 \n",
"2015-01-08 65.70 67.52 65.41 66.64 6889597.0 0.0 1.0 \n",
"2015-01-09 66.76 66.97 64.90 65.34 3488027.0 0.0 1.0 \n",
"2015-01-12 66.16 66.85 63.84 65.92 5246008.0 0.0 1.0 \n",
"2015-01-13 66.84 68.26 65.45 66.41 6265791.0 0.0 1.0 \n",
"\n",
" Adj. Open Adj. High Adj. Low Adj. Close Adj. Volume \n",
"Date \n",
"2015-01-07 64.96 66.11 64.00 65.53 5133939.0 \n",
"2015-01-08 65.70 67.52 65.41 66.64 6889597.0 \n",
"2015-01-09 66.76 66.97 64.90 65.34 3488027.0 \n",
"2015-01-12 66.16 66.85 63.84 65.92 5246008.0 \n",
"2015-01-13 66.84 68.26 65.45 66.41 6265791.0 "
]
},
"execution_count": 106,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"united.head()"
]
},
{
"cell_type": "code",
"execution_count": 107,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style>\n",
" .dataframe thead tr:only-child th {\n",
" text-align: right;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: left;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Open</th>\n",
" <th>High</th>\n",
" <th>Low</th>\n",
" <th>Close</th>\n",
" <th>Volume</th>\n",
" <th>Ex-Dividend</th>\n",
" <th>Split Ratio</th>\n",
" <th>Adj. Open</th>\n",
" <th>Adj. High</th>\n",
" <th>Adj. Low</th>\n",
" <th>Adj. Close</th>\n",
" <th>Adj. Volume</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",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2015-01-07</th>\n",
" <td>53.38</td>\n",
" <td>53.65</td>\n",
" <td>52.12</td>\n",
" <td>53.01</td>\n",
" <td>10069816.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>52.103884</td>\n",
" <td>52.367430</td>\n",
" <td>50.874006</td>\n",
" <td>51.742730</td>\n",
" <td>10069816.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2015-01-08</th>\n",
" <td>53.48</td>\n",
" <td>54.28</td>\n",
" <td>53.25</td>\n",
" <td>53.66</td>\n",
" <td>9672064.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>52.201494</td>\n",
" <td>52.982369</td>\n",
" <td>51.976992</td>\n",
" <td>52.377191</td>\n",
" <td>9672064.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2015-01-09</th>\n",
" <td>53.67</td>\n",
" <td>53.91</td>\n",
" <td>51.82</td>\n",
" <td>52.02</td>\n",
" <td>12290046.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>52.386951</td>\n",
" <td>52.621214</td>\n",
" <td>50.581178</td>\n",
" <td>50.776397</td>\n",
" <td>12290046.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2015-01-12</th>\n",
" <td>51.06</td>\n",
" <td>51.45</td>\n",
" <td>49.20</td>\n",
" <td>49.58</td>\n",
" <td>18261336.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>49.839347</td>\n",
" <td>50.220023</td>\n",
" <td>48.023812</td>\n",
" <td>48.394728</td>\n",
" <td>18261336.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2015-01-13</th>\n",
" <td>50.12</td>\n",
" <td>51.43</td>\n",
" <td>49.46</td>\n",
" <td>50.40</td>\n",
" <td>12259271.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>48.921819</td>\n",
" <td>50.200501</td>\n",
" <td>48.277597</td>\n",
" <td>49.195125</td>\n",
" <td>12259271.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Open High Low Close Volume Ex-Dividend Split Ratio \\\n",
"Date \n",
"2015-01-07 53.38 53.65 52.12 53.01 10069816.0 0.0 1.0 \n",
"2015-01-08 53.48 54.28 53.25 53.66 9672064.0 0.0 1.0 \n",
"2015-01-09 53.67 53.91 51.82 52.02 12290046.0 0.0 1.0 \n",
"2015-01-12 51.06 51.45 49.20 49.58 18261336.0 0.0 1.0 \n",
"2015-01-13 50.12 51.43 49.46 50.40 12259271.0 0.0 1.0 \n",
"\n",
" Adj. Open Adj. High Adj. Low Adj. Close Adj. Volume \n",
"Date \n",
"2015-01-07 52.103884 52.367430 50.874006 51.742730 10069816.0 \n",
"2015-01-08 52.201494 52.982369 51.976992 52.377191 9672064.0 \n",
"2015-01-09 52.386951 52.621214 50.581178 50.776397 12290046.0 \n",
"2015-01-12 49.839347 50.220023 48.023812 48.394728 18261336.0 \n",
"2015-01-13 48.921819 50.200501 48.277597 49.195125 12259271.0 "
]
},
"execution_count": 107,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"american.head()"
]
},
{
"cell_type": "code",
"execution_count": 108,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.legend.Legend at 0x20a50c84400>"
]
},
"execution_count": 108,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\nWuDHFaJ3hsWwe51h93a
"text/plain": [
"<matplotlib.figure.Figure at 0x20a50c66a20>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"american['Adj. Close'].plot(label='American Airlines',figsize=(12,8))\n",
"united['Adj. Close'].plot(label='United Airlines')\n",
"plt.legend()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Spread and Correlation"
]
},
{
"cell_type": "code",
"execution_count": 126,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[ 1. , 0.92145101],\n",
" [ 0.92145101, 1. ]])"
]
},
"execution_count": 126,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.corrcoef(american['Adj. Close'],united['Adj. Close'])"
]
},
{
"cell_type": "code",
"execution_count": 117,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.legend.Legend at 0x20a51bc1710>"
]
},
"execution_count": 117,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAssAAAHMCAYAAAAj5eX+AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzs3XmYXHWZN/zvqVNb19L73p2kO0lnT0hCCDsEDERHQYFX\nER0ddGYcdfARh1ceZUZFR2Z0dPTxdV9edHABXEARFMISAoSQkJA9naSTTqf3vbv2vc7zx6lzuqqr\nqruqqzpVXfX9XBcXSdfSJ0n1Ofe5f/d9/wRJkkBERERERPE0uT4AIiIiIqJ8xWCZiIiIiCgJBstE\nREREREkwWCYiIiIiSoLBMhERERFREgyWiYiIiIiSYLBMRERERJQEg2UiIiIioiQYLBMRERERJcFg\nmYiIiIgoCW2uDyBadXW11NLSkuvDICIiIqICd/DgwVFJkmpme15eBcstLS04cOBArg+DiIiIiAqc\nIAgXUnkeyzCIiIiIiJJgsExERERElASDZSIiIiKiJPKqZpmIiIiI5iYQCKC3txderzfXh5JXjEYj\nmpubodPp5vR6BstEREREBaC3txdWqxUtLS0QBCHXh5MXJEnC2NgYent70draOqf3YBkGERERUQHw\ner2oqqpioBxFEARUVVVllG1nsExERERUIBgox8v074TBMhERERFlxUMPPYS1a9diw4YN2LhxI/bt\n23fRvvfdd9+N3//+91l/X9YsExEREVHG9u7di6effhpvvfUWDAYDRkdH4ff7U3ptMBiEVpufYSkz\ny0RERESUsYGBAVRXV8NgMAAAqqur0djYiJaWFtx///1Yv349tm7dirNnzwKQM8Ef//jHcfnll+P+\n+++Hy+XCRz/6UWzduhWbNm3Cn/70JwBAV1cXrr32WmzevBmbN2/G66+/DkBu3rvnnnuwcuVKbN++\nHcPDw/Py58rPEJ6IiIiI5uzLfz6Bk/32rL7nmsZSfOmWtUkfv/nmm/GVr3wFK1aswPbt23HnnXfi\n+uuvBwCUlZXh2LFjeOSRR3Dvvffi6aefBiBP8Hj99dchiiIeeOAB3HjjjXj44YcxOTmJrVu3Yvv2\n7aitrcXzzz8Po9GIjo4O3HXXXThw4ACefPJJnD59GidPnsTQ0BDWrFmDj370o1n9MwMMlomIiIgo\nCywWCw4ePIhXX30Vu3btwp133omvfe1rAIC77rpL/f9nPvMZ9TXvfe97IYoiAGDnzp146qmn8M1v\n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\nMq1ZNupESBLg8AWzeVh
"text/plain": [
"<matplotlib.figure.Figure at 0x20a51a47c18>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"spread = american['Adj. Close'] - united['Adj. Close']\n",
"spread.plot(label='Spread',figsize=(12,8))\n",
"plt.axhline(spread.mean(),c='r')\n",
"plt.legend()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Normalizing with a z-score"
]
},
{
"cell_type": "code",
"execution_count": 119,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def zscore(stocks):\n",
" return (stocks - stocks.mean()) / np.std(stocks)"
]
},
{
"cell_type": "code",
"execution_count": 127,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAzQAAAHMCAYAAAADLO0qAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzs3XecVPW5P/DPmb4z2ztb6ALSmyAiikjUGDUhtktsxOTG\nhJgbc01y8/NeozEaY+KNmlxNMTHWGCtqELsgCghSlrqUBZbtZXZ3ZqfX8/vjzDnb28zZnZndz/v1\n4sUy5cx32dlz5vk+z/f5CqIogoiIiIiIKBlp4j0AIiIiIiKiaDGgISIiIiKipMWAhoiIiIiIkhYD\nGiIiIiIiSloMaIiIiIiIKGkxoCEiIiIioqTFgIaIiIiIiJIWAxoiIiIiIkpaDGiIiIiIiChpMaAh\nIiIiIqKkpYvHi+bm5ooTJ06Mx0sTEREREVES2LNnj1UUxbyBHheXgGbixInYvXt3PF6aiIiIiIiS\ngCAIZwbzOJacERERERFR0mJAQ0RERERESYsBDRERERERJa24rKEhIiIiIhoOgUAANTU18Hq98R4K\nDZLJZEJJSQn0en1Uz2dAQ0RERESjRk1NDdLS0jBx4kQIghDv4dAARFFES0sLampqMGnSpKiOwZIz\nIiIiIho1vF4vcnJyGMwkCUEQkJOTE1NGjQENEREREY0qDGaSS6w/LwY0REREREQqeuCBBzBr1izM\nnTsX8+fPx86dO0f09detW4dXX311RF8znriGhoiIiIhIJTt27MDGjRuxd+9eGI1GWK1W+P3+QT8/\nGAxCpxsdH9FH6nthhoaIiIiISCX19fXIzc2F0WgEAOTm5qKoqAgAMHHiRPz0pz/FnDlzsGTJElRU\nVACQMirf/e53sXTpUvz0pz+Fy+XCrbfeiiVLlmDBggV48803AQCVlZVYsWIFFi5ciIULF2L79u0A\npIX1t99+O6ZPn47Vq1ejqampx7jq6uowf/585Y9Wq8WZM2e6PCYUCmHdunWYPXs25syZg0ceeQQA\nUFFRgdWrV2PevHlYuHAhTp48CVEU8ZOf/ER57EsvvQQA2LJlC1asWIGrrroKM2fOBAA8//zzWLJk\nCebPn4/bbrsNoVBI1f/z0RH+ERERERF184t/HcaRunZVjzmzKB33XDmrz/svueQS3HfffZg2bRpW\nr16N66+/HhdeeKFyf0ZGBg4ePIhnn30Wd9xxBzZu3AhA6s62fft2aLVa3HXXXVi1ahWeeuop2Gw2\nLFmyBKtXr0Z+fj4++OADmEwmnDhxAmvXrsXu3buxYcMGHDt2DEeOHEFjYyNmzpyJW2+9tcu4ioqK\nUFZWBgB4/PHH8cknn2DChAldHlNWVoba2locOnQIAGCz2QAAN9xwA372s59hzZo18Hq9CIfDeP31\n11FWVob9+/fDarXinHPOwQUXXAAA2Lt3Lw4dOoRJkyahvLwcL730ErZt2wa9Xo/169fjhRdewM03\n3xzjT6IDAxoiIiIiIpWkpqZiz549+PTTT7F582Zcf/31+PWvf41169YBANauXav8/aMf/Uh53rXX\nXgutVgsAeP/99/HWW2/h4YcfBiB1bquqqkJRURFuv/12lJWVQavV4vjx4wCArVu3Yu3atdBqtSgq\nKsKqVav6HN+2bdvw5JNP4rPPPutx3+TJk3Hq1Cn84Ac/wFe+8hVccsklcDgcqK2txZo1awBIe8YA\nwGeffaa8ZkFBAS688EJ88cUXSE9Px5IlS5QWzB999BH27NmDc845BwDg8XiQn58f9f9vbxjQEBER\nEdGo1F8mZThptVqsXLkSK1euxJw5c/DMM88oAU3njl6dv7ZYLMrXoijitddew/Tp07sc995770VB\nQQH279+PcDisBBeDVV9fj29961t46623kJqailAohEWLFgEArrrqKtx3333Yv38/3nvvPfzpT3/C\nyy+/jMcee2yo336P7+WWW27Bgw8+OOTjDBbX0BARERERqeTYsWM4ceKE8u+ysrIupV3yWpOXXnoJ\ny5Yt6/UYl156Kf7whz9AFEUAwL59+wAAdrsd48aNg0ajwXPPPaesRbngggvw0ksvIRQKob6+Hps3\nb+5xzEAggGuvvRYPPfQQpk2bBkAKvMrKylBWVob77rsPVqsV4XAYV199Ne6//37s3bsXaWlpKCkp\nwRtvvAEA8Pl8cLvdWLFihfKazc3N2Lp1K5YsWdLjdS+++GK8+uqryrqe1tbWHmt3YsUMDRERJS1R\nFPFReRMumpEPrYb7ThBR/DmdTvzgBz+AzWaDTqfD1KlT8Ze//EW5v62tDXPnzoXRaMSLL77Y6zHu\nvvtu3HHHHZg7dy7C4TAmTZqEjRs3Yv369bj66qvx7LPP4rLLLlMyIWvWrMHHH3+MmTNnYvz48b0G\nStu3b8fu3btxzz334J577gEAbNq0SWlYAAC1tbX45je/iXA4DABKVuW5557Dbbfdhp///OfQ6/V4\n5ZVXsGbNGuzYsQPz5s2DIAj4zW9+g8LCQhw9erTL686cORP3338/LrnkEoTDYej1ejz++OM91u/E\nQpAjv5G0ePFicffu3SP+ukRENLrsrmzFNX/agWdvXYILpuXFezhElADKy8tx9tlnx3sYvZo4cSJ2\n796N3NzceA8l4fT2cxMEYY8oiosHei5LzoiIKGlVtrgBAK2uwe/xQEREowtLzoiIKGnVtnkAAA5v\nIM4jISIaWGVlZbyHMCoxQ0NEREmrpk3K0LR7g3EeCRERxQsDGiIiSlo1kQxNu4cZGiKisYoBDRER\nJa1aWySgYYaGiGjMYkBDRERJKRQWUacENMzQEBGNVQxoiIgoKTW2exEMS1sPsOSMiBKJIAi48cYb\nlX8Hg0Hk5eXhiiuuiOOoRi8GNERElJTkcjO9VoCDJWdElEAsFgsOHToEj0c6T33wwQcoLi6O86hG\nLwY0RESUlA7U2AEAc4ozWHJGRAnn8ssvx9tvvw0AePHFF7F27VrlPpfLhVtvvRVLlizBggUL8Oab\nbwKQ2jqvWLECCxcuxMKFC7F9+3YAwJYtW7By5Upcc801mDFjBm644QaIojjy31SC4j40RESUlHad\nbkFpdgqmF6bjgyON8R4OESWgO+64A2VlZaoec/78+Xj00UcHfNy//du/4b777sMVV1yBAwcO4NZb\nb8Wnn34KAHjggQewatUqPPXUU7DZbFiyZAlWr16N/Px8fPDBBzCZTDhx4gTWrl2L3bt3AwD27duH\nw4cPo6ioCMuXL8e2bdtw/vnnq/q9JSsGNERElHTCYRG7Trfi4rMLkG7ScWNNIko4c+fORWVlJV58\n8UVcfvnlXe57//338dZbb+Hhhx8GAHi9XlRVVaGoqAi33347ysrKoNVqcfz4ceU5S5YsQUlJCQAp\nqKqsrGRAE8GAhoiIks6JJifa3AEsmZSNZocPvmAY3kAIJr023kMjogQymEzKcLrqqqvw4x//GFu2\nbEFLS4tyuyiKeO211zB9+vQuj7/33ntRUFCA/fv3IxwOw2QyKfcZjUbla61Wi2CQawdlXENDRERJ\n54MjDQCAZZNzkGaS5ubYGICIEs2tt96Ke+65B3PmzOly+6WXXoo//OEPyjqYffv2AQDsdjvGjRsH\njUaD5557DqFQaMTHnIwY0BARUVIJhMJ4/vMqrDgrF6XZZqSb9ADAsjMiSjglJSX4j//4jx633333\n3QgEApg7dy5mzZqFu+++GwCwfv16PPPMM5g3bx6OHj0Ki8Uy0kNOSkI8OiQsXrxYlBc4ERERDcXG\nA3W4/R/78NebF2P1zAJ8fLQRtz69G298fznml2bGe3hEFGfl5eU4++yz4z0MGqLefm6CIOwRRXHx\nQM9lhoaIiJLKM9srUZqdgotm5AMA0iIZGm6uSUQ0NjGgISKipHG4zo4vKttwy7KJ0GoEAFBKzuwM\naIiIxiQGNERElDSe2V6JFL0W1y4uVW4rzU6BIAAVTc44joyIiOKFAQ0RESWFVpcfb5bVYc3CYmSk\n6JXbzQYdJudacLiuPY6
"text/plain": [
"<matplotlib.figure.Figure at 0x20a52618438>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"zscore(spread).plot(figsize=(14,8))\n",
"plt.axhline(zscore(spread).mean(), color='black')\n",
"plt.axhline(1.0, c='r', ls='--')\n",
"plt.axhline(-1.0, c='g', ls='--')\n",
"plt.legend(['Spread z-score', 'Mean', '+1', '-1']);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Rolling Z-Score\n",
"\n",
"Our spread is currently American-United. Let's decide how to calculate this on a rolling basis for our use in Quantopian"
]
},
{
"cell_type": "code",
"execution_count": 133,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\nEhXFBEG4I0YM+41k68e
"text/plain": [
"<matplotlib.figure.Figure at 0x20a52c60eb8>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#1 day moving average of the price spread\n",
"spread_mavg1 = spread.rolling(1).mean()\n",
"\n",
"# 30 day moving average of the price spread\n",
"spread_mavg30 = spread.rolling(30).mean()\n",
"\n",
"# Take a rolling 30 day standard deviation\n",
"std_30 = spread.rolling(30).std()\n",
"\n",
"# Compute the z score for each day\n",
"zscore_30_1 = (spread_mavg1 - spread_mavg30)/std_30\n",
"\n",
"\n",
"\n",
"zscore_30_1.plot(figsize=(12,8),label='Rolling 30 day Z score')\n",
"plt.axhline(0, color='black')\n",
"plt.axhline(1.0, color='red', linestyle='--');"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Implementation of Strategy\n",
"\n",
"#### WARNING: YOU SHOULD NOT ACTUALLY TRADE WITH THIS!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import numpy as np\n",
" \n",
"def initialize(context):\n",
" \"\"\"\n",
" Called once at the start of the algorithm.\n",
" \"\"\" \n",
" \n",
" # Every day we check the pair status\n",
" schedule_function(check_pairs, date_rules.every_day(), time_rules.market_close(minutes=60))\n",
" \n",
" # Our Two Airlines\n",
" context.aa = sid(45971) #aal\n",
" context.ual = sid(28051) #ual \n",
" \n",
" # Flags to tell us if we're currently in a trade\n",
" context.long_on_spread = False\n",
" context.shorting_spread = False\n",
"\n",
"\n",
"def check_pairs(context, data):\n",
" \n",
" # For convenience\n",
" aa = context.aa\n",
" ual = context.ual\n",
" \n",
" # Get pricing history\n",
" prices = data.history([aa, ual], \"price\", 30, '1d')\n",
" \n",
" \n",
" # Need to use .iloc[-1:] to get dataframe instead of series\n",
" short_prices = prices.iloc[-1:]\n",
" \n",
" # Get the long 30 day mavg\n",
" mavg_30 = np.mean(prices[aa] - prices[ual])\n",
" \n",
" # Get the std of the 30 day long window\n",
" std_30 = np.std(prices[aa] - prices[ual])\n",
" \n",
" # Get the shorter span 1 day mavg\n",
" mavg_1 = np.mean(short_prices[aa] - short_prices[ual])\n",
" \n",
" # Compute z-score\n",
" if std_30 > 0:\n",
" zscore = (mavg_1 - mavg_30)/std_30\n",
" \n",
" # Our two entry cases\n",
" if zscore > 0.5 and not context.shorting_spread:\n",
" # spread = aa - ual\n",
" order_target_percent(aa, -0.5) # short top\n",
" order_target_percent(ual, 0.5) # long bottom\n",
" context.shorting_spread = True\n",
" context.long_on_spread = False\n",
" \n",
" elif zscore < -0.5 and not context.long_on_spread:\n",
" # spread = aa - ual\n",
" order_target_percent(aa, 0.5) # long top\n",
" order_target_percent(ual, -0.5) # short bottom\n",
" context.shorting_spread = False\n",
" context.long_on_spread = True\n",
" \n",
" # Our exit case\n",
" elif abs(zscore) < 0.1:\n",
" order_target_percent(aa, 0)\n",
" order_target_percent(ual, 0)\n",
" context.shorting_spread = False\n",
" context.long_on_spread = False\n",
" \n",
" record('zscore', zscore)"
]
}
],
"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.1"
}
},
"nbformat": 4,
"nbformat_minor": 1
}