{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "#Traditional Value Factor Algorithm\n", "\n", "By Gil Wassermann\n", "\n", "Strategy taken from \"130/30: The New Long-Only\" by Andrew Lo and Pankaj Patel\n", "\n", "Part of the Quantopian Lecture Series:\n", "* www.quantopian.com/lectures\n", "* github.com/quantopian/research_public\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Before the crisis of 2007, 130/30 funds were all the rage. The idea of a 130/30 fund is simple: take a long position of 130% and a short position of 30%; this combination gives a net exposure of 100% (the same as a long-only fund) as well as the added benefit of the ability to short stocks. The ability to short in a trading strategy is crucial as it allows a fund manager to capitalize on a security's poor performance, which is impossible in a traditional, long-only strategy.\n", "\n", "This notebook, using factors outlined by Andrew Lo and Pankaj Patel in \"130/30: The New Long Only\", will demonstrate how to create an algorithmic 130/30 strategy. It will also highlight Quantopian's Pipeline API which is a powerful tool for developing factor trading strategies." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, let us import all necessary libraries and functions for this algorithm" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "from quantopian.pipeline import Pipeline\n", "from quantopian.pipeline.data.builtin import USEquityPricing\n", "from quantopian.research import run_pipeline\n", "from quantopian.pipeline.data import Fundamentals\n", "from quantopian.pipeline.factors import CustomFactor" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#Traditional Value\n", "\n", "In this notebook, we will develop a strategy based on the \"traditional value\" metrics described in the Lo/Patel whitepaper. The factors employed in this strategy designate stocks as either cheap or expensive using classic fundamental analysis. The factors that Lo/Patel used are:\n", "\n", "* Dividend Yield\n", "* Price to Book Value\n", "* Price to Trailing 12-Month Sales\n", "* Price to Trainling 12-Month Cash Flows" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Dividend Yield\n", "\n", "Dividend yield is calculated as:\n", "\n", "$$Dividend\\;Yield = \\frac{Annual\\;Dividends\\;per\\;share}{Price\\;per\\;share}$$\n", "\n", "When a company makes profit, it faces a choice. It could either reinvest those profits in the company with an eye to increase efficiency, purchase new technology, etc. or it could pay dividends to its equity holders. While reinvestment may increase a company's future share price and thereby reward investors, the most concrete way equity holders are rewarded is through dividends. An equity with a high dividend yield is particularly attractive as the quantity of dividends paid to investors represent a larger proportion of the share price itself. Now we shall create a Dividend Yield factor using the Pipeline API framework and Pipeline's list of fundamental values." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Custom Factor 1 : Dividend Yield\n", "class Div_Yield(CustomFactor):\n", " inputs = [Fundamentals.div_yield5_year]\n", " window_length = 1\n", " def compute(self, today, assets, out, d_y):\n", " out[:] = d_y[-1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "While this factor could be calculated using other fundamental metrics, Fundamentals removes the need for any calculation. It is good practice to check the list of [fundamentals](https://www.quantopian.com/help/fundamentals) before creating a custom factor from scratch.\n", "\n", "We will initialize a temporary Pipeline to get a sense of the values." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Dividend Yield
2015-11-11 00:00:00+00:00Equity(2 [ARNC])0.0110
Equity(41 [ARCB])0.0064
Equity(52 [ABM])0.0240
Equity(62 [ABT])0.0279
Equity(64 [ABX])0.0192
\n", "
" ], "text/plain": [ " Dividend Yield\n", "2015-11-11 00:00:00+00:00 Equity(2 [ARNC]) 0.0110\n", " Equity(41 [ARCB]) 0.0064\n", " Equity(52 [ABM]) 0.0240\n", " Equity(62 [ABT]) 0.0279\n", " Equity(64 [ABX]) 0.0192" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# create the pipeline\n", "temp_pipe_1 = Pipeline()\n", "\n", "# add the factor to the pipeline\n", "temp_pipe_1.add(Div_Yield(), 'Dividend Yield')\n", "\n", "# run the pipeline and get data for first 5 equities\n", "run_pipeline(temp_pipe_1, start_date = '2015-11-11', end_date = '2015-11-11').dropna().head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Price to Book Value\n", "\n", "Price to Book Value (a.k.a Price to Book Ratio) is calculated as:\n", "\n", "$$P/B\\;Ratio = \\frac{Price\\;per\\;share}{Net\\;Asset\\;Value\\;per\\;share}$$\n", "\n", "Net Asset Value per share can be thought of (very roughly) as a company's total assets less its total liabilities, all divided by the number of shares outstanding.\n", "\n", "The P/B Ratio gives a sense of a stock being either over- or undervalued. A high P/B ratio suggests that a stock's price is overvalued, and should therefore be shorted, whereas a low P/B ratio is attractive as the stock gained by purchasing the equity is hypothetically \"worth more\" than the price paid for it. \n", "\n", "We will now create a P/B Ratio custom factor and look at some of the results." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
P/B Ratio
2015-11-11 00:00:00+00:00Equity(2 [ARNC])0.899825
Equity(21 [AAME])0.976077
Equity(24 [AAPL])5.632086
Equity(25 [ARNC_PR])NaN
Equity(31 [ABAX])5.281542
\n", "
" ], "text/plain": [ " P/B Ratio\n", "2015-11-11 00:00:00+00:00 Equity(2 [ARNC]) 0.899825\n", " Equity(21 [AAME]) 0.976077\n", " Equity(24 [AAPL]) 5.632086\n", " Equity(25 [ARNC_PR]) NaN\n", " Equity(31 [ABAX]) 5.281542" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Custom Factor 2 : P/B Ratio\n", "class Price_to_Book(CustomFactor):\n", " inputs = [Fundamentals.pb_ratio]\n", " window_length = 1\n", "\n", " def compute(self, today, assets, out, pbr):\n", " out[:] = pbr[-1]\n", " \n", "# create the Pipeline\n", "temp_pipe_2 = Pipeline()\n", "\n", "# add the factor to the Pipeline\n", "temp_pipe_2.add(Price_to_Book(), 'P/B Ratio')\n", "\n", "# run the Pipeline and get data for first 5 equities\n", "run_pipeline(temp_pipe_2, start_date='2015-11-11', end_date='2015-11-11').head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are two points to make about this data series. \n", "\n", "Firstly, AA_PR's P/B Ratio is given as NaN by Pipeline. NaN stands for \"not a number\" and occurs when a value can not be fetched by Pipeline. Eventually, we will remove these NaN values from the dataset as they often lead to confusing errors when manipulating the data.\n", "\n", "Secondly, a low P/B Ratio and a high Dividend Yield are attractive for investors, whereas a a high P/B Ratio and a low Dividend Yield are unattractive. Therefore, we will \"invert\" the P/B ratio by making each value negative in the factor output so that, when the data is aggregated later in the algorithm, the maxima and minima have the same underlying \"meaning\"." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Price to Trailing 12-Month Sales\n", "\n", "This is calculated as a simple ratio between price per share and trailing 12-month (TTM) sales. \n", "\n", "TTM is a transformation rather than a metric and effectively calculates improvement or deterioration of a fundamental value from a particular quarter one year previously. For example, if one wanted to calculate today's TTM Sales for company XYZ, one would take the most recent quarter's revenue and divide it by the difference between this quarter's revenue and this quarter's revenue last year added to the revenue as given by the company's most recent fiscal year-end filing.\n", "\n", "To calculate the exact TTM of a security is indeed possible using Pipeline; however, the code required is slow. Luckily, this value can be well approximated by the built-in Fundamental Morningstar ratios, which use annual sales to calculate the Price to Sales fundamental value. This slight change boosts the code's speed enormously yet has very little impact on the results of the strategy itself." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Price to TTM Sales is similar to the P/B Ratio in terms of function. The major difference in these two ratios is the fact that inclusion of TTM means that seasonal fluctuations are minimized, as previous data is used to smooth the value. In our case, annualized values accomplish this same smoothing.\n", "\n", "Also, note that the values produced are negative; this factor requires the same inversion as the P/B Ratio." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Price / TTM Sales
2015-11-11 00:00:00+00:00Equity(2 [ARNC])-0.453038
Equity(21 [AAME])-0.629844
Equity(24 [AAPL])-2.988556
Equity(25 [ARNC_PR])NaN
Equity(31 [ABAX])-5.640918
\n", "
" ], "text/plain": [ " Price / TTM Sales\n", "2015-11-11 00:00:00+00:00 Equity(2 [ARNC]) -0.453038\n", " Equity(21 [AAME]) -0.629844\n", " Equity(24 [AAPL]) -2.988556\n", " Equity(25 [ARNC_PR]) NaN\n", " Equity(31 [ABAX]) -5.640918" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Custom Factor 3 : Price to Trailing 12 Month Sales \n", "class Price_to_TTM_Sales(CustomFactor):\n", " inputs = [Fundamentals.ps_ratio]\n", " window_length = 1\n", " \n", " def compute(self, today, assets, out, ps):\n", " out[:] = -ps[-1]\n", " \n", "# create the pipeline\n", "temp_pipe_3 = Pipeline()\n", "\n", "# add the factor to the pipeline\n", "temp_pipe_3.add(Price_to_TTM_Sales(), 'Price / TTM Sales')\n", "\n", "# run the pipeline and get data for first 5 equities\n", "run_pipeline(temp_pipe_3, start_date='2015-11-11', end_date='2015-11-11').head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Price to Trailing 12-Month Cashflows\n", "\n", "This is calculated as a simple ratio between price per share and TTM free cashflow (here using the built-in Fundamental Morningstar ratio as an approximaton).\n", "\n", "This ratio serves a similar function to the previous two. A future notebook will explore the subtle differences in these metrics, but they largely serve the same purpose. Once again, low values are attractive and high values are unattractive, so the metric must be inverted." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Price / TTM Cashflows
2015-11-11 00:00:00+00:00Equity(2 [ARNC])-4.929472
Equity(21 [AAME])-34.732899
Equity(24 [AAPL])-8.594865
Equity(25 [ARNC_PR])NaN
Equity(31 [ABAX])-42.920180
\n", "
" ], "text/plain": [ " Price / TTM Cashflows\n", "2015-11-11 00:00:00+00:00 Equity(2 [ARNC]) -4.929472\n", " Equity(21 [AAME]) -34.732899\n", " Equity(24 [AAPL]) -8.594865\n", " Equity(25 [ARNC_PR]) NaN\n", " Equity(31 [ABAX]) -42.920180" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Custom Factor 4 : Price to Trailing 12 Month Cashflow\n", "class Price_to_TTM_Cashflows(CustomFactor):\n", " inputs = [Fundamentals.pcf_ratio]\n", " window_length = 1\n", " \n", " def compute(self, today, assets, out, pcf):\n", " out[:] = -pcf[-1] \n", " \n", "# create the pipeline\n", "temp_pipe_4 = Pipeline()\n", "\n", "# add the factor to the pipeline\n", "temp_pipe_4.add(Price_to_TTM_Cashflows(), 'Price / TTM Cashflows')\n", "\n", "# run the pipeline and get data for first 5 equities\n", "run_pipeline(temp_pipe_4, start_date='2015-11-11', end_date='2015-11-11').head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##The Full Pipeline\n", "\n", "Now that each individual factor has been added, it is now time to get all the necessary data at once. In the algorithm, this will take place once every day.\n", "\n", "Later in the process, we will need a factor in order to create an approximate S&P500, so we will also include another factor called SPY_proxy (SPY is an ETF that tracks the S&P500). The S&P500 is a collection of 500 of the largest companies traded on the stock market. Our interpretation of the S&P500 is a group of 500 companies with the greatest market capitalizations; however, the actual S&P500 will be slightly different as Standard and Poors, who create the index, have a more nuanced algorithm for calculation.\n", "\n", "We will also alter our P/B Ratio factor in order to account for the inversion." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Dividend YieldPrice / TTM CashflowPrice / TTM SalesPrice to BookSPY Proxy
2015-11-11 00:00:00+00:00Equity(2 [ARNC])0.011-4.929472-0.453038-0.8998251.128021e+10
Equity(21 [AAME])NaN-34.732899-0.629844-0.9760771.029634e+08
Equity(24 [AAPL])NaN-8.594865-2.988556-5.6320866.722177e+11
Equity(25 [ARNC_PR])NaNNaNNaNNaNNaN
Equity(31 [ABAX])NaN-42.920180-5.640918-5.2815421.186963e+09
\n", "
" ], "text/plain": [ " Dividend Yield \\\n", "2015-11-11 00:00:00+00:00 Equity(2 [ARNC]) 0.011 \n", " Equity(21 [AAME]) NaN \n", " Equity(24 [AAPL]) NaN \n", " Equity(25 [ARNC_PR]) NaN \n", " Equity(31 [ABAX]) NaN \n", "\n", " Price / TTM Cashflow \\\n", "2015-11-11 00:00:00+00:00 Equity(2 [ARNC]) -4.929472 \n", " Equity(21 [AAME]) -34.732899 \n", " Equity(24 [AAPL]) -8.594865 \n", " Equity(25 [ARNC_PR]) NaN \n", " Equity(31 [ABAX]) -42.920180 \n", "\n", " Price / TTM Sales \\\n", "2015-11-11 00:00:00+00:00 Equity(2 [ARNC]) -0.453038 \n", " Equity(21 [AAME]) -0.629844 \n", " Equity(24 [AAPL]) -2.988556 \n", " Equity(25 [ARNC_PR]) NaN \n", " Equity(31 [ABAX]) -5.640918 \n", "\n", " Price to Book SPY Proxy \n", "2015-11-11 00:00:00+00:00 Equity(2 [ARNC]) -0.899825 1.128021e+10 \n", " Equity(21 [AAME]) -0.976077 1.029634e+08 \n", " Equity(24 [AAPL]) -5.632086 6.722177e+11 \n", " Equity(25 [ARNC_PR]) NaN NaN \n", " Equity(31 [ABAX]) -5.281542 1.186963e+09 " ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# This factor creates the synthetic S&P500\n", "class SPY_proxy(CustomFactor):\n", " inputs = [Fundamentals.market_cap]\n", " window_length = 1\n", " \n", " def compute(self, today, assets, out, mc):\n", " out[:] = mc[-1]\n", " \n", "# Custom Factor 2 : P/B Ratio\n", "class Price_to_Book(CustomFactor):\n", " inputs = [Fundamentals.pb_ratio]\n", " window_length = 1\n", "\n", " def compute(self, today, assets, out, pbr):\n", " out[:] = -pbr[-1]\n", " \n", "def Data_Pull():\n", " \n", " # create the piepline for the data pull\n", " Data_Pipe = Pipeline()\n", " \n", " # create SPY proxy\n", " Data_Pipe.add(SPY_proxy(), 'SPY Proxy')\n", "\n", " # Div Yield\n", " Data_Pipe.add(Div_Yield(), 'Dividend Yield') \n", " \n", " # Price to Book\n", " Data_Pipe.add(Price_to_Book(), 'Price to Book')\n", " \n", " # Price / TTM Sales\n", " Data_Pipe.add(Price_to_TTM_Sales(), 'Price / TTM Sales')\n", " \n", " # Price / TTM Cashflows\n", " Data_Pipe.add(Price_to_TTM_Cashflows(), 'Price / TTM Cashflow')\n", " \n", " return Data_Pipe\n", "\n", "# NB: Data pull is a function that returns a Pipeline object, so need ()\n", "results = run_pipeline(Data_Pull(), start_date='2015-11-11', end_date='2015-11-11')\n", "results.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Aggregation\n", "\n", "Now that we have all our data, we need to manipulate this in order to create a single ranking of the securities. Lo/Patel recommend the following algorithm:\n", "\n", "* Extract the S&P500 from the set of equities and find the mean and standard deviation of each factor for this dataset (standard_frame_compute)\n", "\n", "* Use these computed values to standardize each factor (standard_frame_compute)\n", "\n", "* Replace values that are greater that 10 or less that -10 with 10 and -10 respectively in order to limit the effect of outliers (filter_fn)\n", "\n", "* Sum these values for each equity and divide by the number of factors in order to give a value between -10 and 10 (composite score)\n", "\n", "The code for this is shown below." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python2.7/dist-packages/ipykernel_launcher.py:17: FutureWarning: sort(columns=....) is deprecated, use sort_values(by=.....)\n", "/usr/local/lib/python2.7/dist-packages/ipykernel_launcher.py:66: FutureWarning: sort is deprecated, use sort_values(inplace=True) for INPLACE sorting\n" ] }, { "data": { "text/plain": [ "(2015-11-11 00:00:00+00:00, Equity(35162 [ARR])) 1.941979\n", "(2015-11-11 00:00:00+00:00, Equity(27019 [WIN])) 1.670852\n", "(2015-11-11 00:00:00+00:00, Equity(39622 [NKA])) 1.631767\n", "(2015-11-11 00:00:00+00:00, Equity(28076 [RSO])) 1.575746\n", "(2015-11-11 00:00:00+00:00, Equity(32675 [BBEP])) 1.508037\n", "(2015-11-11 00:00:00+00:00, Equity(27993 [LINE])) 1.448997\n", "(2015-11-11 00:00:00+00:00, Equity(11461 [DOM])) 1.439093\n", "(2015-11-11 00:00:00+00:00, Equity(24102 [NRP])) 1.415778\n", "(2015-11-11 00:00:00+00:00, Equity(5061 [MSFT])) 1.408201\n", "(2015-11-11 00:00:00+00:00, Equity(34662 [NYMT])) 1.333686\n", "(2015-11-11 00:00:00+00:00, Equity(8347 [XOM])) 1.324958\n", "(2015-11-11 00:00:00+00:00, Equity(33159 [LGCY])) 1.251848\n", "(2015-11-11 00:00:00+00:00, Equity(33178 [MVO])) 1.247968\n", "(2015-11-11 00:00:00+00:00, Equity(38477 [CYS])) 1.226731\n", "(2015-11-11 00:00:00+00:00, Equity(35054 [NMM])) 1.213649\n", "(2015-11-11 00:00:00+00:00, Equity(3149 [GE])) 1.178168\n", "(2015-11-11 00:00:00+00:00, Equity(38887 [TWO])) 1.170784\n", "(2015-11-11 00:00:00+00:00, Equity(40060 [FULL])) 1.162997\n", "(2015-11-11 00:00:00+00:00, Equity(26517 [PSEC])) 1.160164\n", "(2015-11-11 00:00:00+00:00, Equity(6653 [T])) 1.146484\n", "(2015-11-11 00:00:00+00:00, Equity(21907 [MNDO])) 1.107410\n", "(2015-11-11 00:00:00+00:00, Equity(32443 [PGH])) 1.087876\n", "(2015-11-11 00:00:00+00:00, Equity(32293 [OBE])) 1.056844\n", "(2015-11-11 00:00:00+00:00, Equity(7143 [SAN])) 1.049898\n", "(2015-11-11 00:00:00+00:00, Equity(17657 [ORAN])) 1.046273\n", "(2015-11-11 00:00:00+00:00, Equity(27487 [RDS_A])) 1.040481\n", "(2015-11-11 00:00:00+00:00, Equity(39942 [AT])) 1.038906\n", "(2015-11-11 00:00:00+00:00, Equity(34931 [VNR])) 1.034368\n", "(2015-11-11 00:00:00+00:00, Equity(33024 [KCAP])) 1.026654\n", "(2015-11-11 00:00:00+00:00, Equity(27470 [RDS_B])) 1.022292\n", " ... \n", "(2015-11-11 00:00:00+00:00, Equity(26017 [UTG])) -0.982711\n", "(2015-11-11 00:00:00+00:00, Equity(26781 [MKTX])) -0.983476\n", "(2015-11-11 00:00:00+00:00, Equity(34797 [MAIN])) -1.026855\n", "(2015-11-11 00:00:00+00:00, Equity(1068 [BPT])) -1.153233\n", "(2015-11-11 00:00:00+00:00, Equity(41886 [FNV])) -1.172843\n", "(2015-11-11 00:00:00+00:00, Equity(22545 [NXJ])) -1.209950\n", "(2015-11-11 00:00:00+00:00, Equity(28356 [GLO])) -1.214150\n", "(2015-11-11 00:00:00+00:00, Equity(18522 [ARMH])) -1.248968\n", "(2015-11-11 00:00:00+00:00, Equity(27200 [GLQ])) -1.287656\n", "(2015-11-11 00:00:00+00:00, Equity(26521 [GLV])) -1.289762\n", "(2015-11-11 00:00:00+00:00, Equity(7551 [TPL])) -1.306126\n", "(2015-11-11 00:00:00+00:00, Equity(40168 [CFD])) -1.336972\n", "(2015-11-11 00:00:00+00:00, Equity(24489 [GLNG])) -1.348952\n", "(2015-11-11 00:00:00+00:00, Equity(5272 [NRT])) -1.370774\n", "(2015-11-11 00:00:00+00:00, Equity(24731 [LEN_B])) -1.519243\n", "(2015-11-11 00:00:00+00:00, Equity(1423 [CET])) -1.525415\n", "(2015-11-11 00:00:00+00:00, Equity(4263 [KMB])) -1.531782\n", "(2015-11-11 00:00:00+00:00, Equity(2382 [DXR])) -1.561114\n", "(2015-11-11 00:00:00+00:00, Equity(2404 [EAT])) -1.562417\n", "(2015-11-11 00:00:00+00:00, Equity(35902 [PM])) -1.570361\n", "(2015-11-11 00:00:00+00:00, Equity(1936 [CSWC])) -1.618194\n", "(2015-11-11 00:00:00+00:00, Equity(26414 [FEN])) -1.750639\n", "(2015-11-11 00:00:00+00:00, Equity(20277 [RAI])) -1.769105\n", "(2015-11-11 00:00:00+00:00, Equity(4417 [LEN])) -1.885524\n", "(2015-11-11 00:00:00+00:00, Equity(2420 [ECF])) -1.917463\n", "(2015-11-11 00:00:00+00:00, Equity(4849 [SPGI])) -1.927483\n", "(2015-11-11 00:00:00+00:00, Equity(33555 [CQP])) -2.062992\n", "(2015-11-11 00:00:00+00:00, Equity(4564 [LB])) -2.086269\n", "(2015-11-11 00:00:00+00:00, Equity(5281 [NEN])) -2.200646\n", "(2015-11-11 00:00:00+00:00, Equity(13508 [CLB])) -2.521344\n", "dtype: float64" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# limit effect of outliers\n", "def filter_fn(x):\n", " if x <= -10:\n", " x = -10.0\n", " elif x >= 10:\n", " x = 10.0\n", " return x \n", "\n", "# standardize using mean and sd of S&P500\n", "def standard_frame_compute(df):\n", " \n", " # basic clean of dataset to remove infinite values\n", " df = df.replace([np.inf, -np.inf], np.nan)\n", " df = df.dropna()\n", " \n", " # need standardization params from synthetic S&P500\n", " df_SPY = df.sort(columns='SPY Proxy', ascending=False)\n", "\n", " # create separate dataframe for SPY\n", " # to store standardization values\n", " df_SPY = df_SPY.head(500)\n", " \n", " # get dataframes into numpy array\n", " df_SPY = df_SPY.as_matrix()\n", " \n", " # store index values\n", " index = df.index.values\n", " df = df.as_matrix()\n", " \n", " df_standard = np.empty(df.shape[0])\n", " \n", " \n", " for col_SPY, col_full in zip(df_SPY.T, df.T):\n", " \n", " # summary stats for S&P500\n", " mu = np.mean(col_SPY)\n", " sigma = np.std(col_SPY)\n", " col_standard = np.array(((col_full - mu) / sigma)) \n", "\n", " # create vectorized function (lambda equivalent)\n", " fltr = np.vectorize(filter_fn)\n", " col_standard = (fltr(col_standard))\n", " \n", " # make range between -10 and 10\n", " col_standard = (col_standard / df.shape[1])\n", " \n", " # attach calculated values as new row in df_standard\n", " df_standard = np.vstack((df_standard, col_standard))\n", " \n", " # get rid of first entry (empty scores)\n", " df_standard = np.delete(df_standard,0,0)\n", " \n", " return (df_standard, index)\n", "\n", "# Sum up and sort data\n", "def composite_score(df, index):\n", "\n", " # sum up transformed data\n", " df_composite = df.sum(axis=0)\n", " \n", " # put into a pandas dataframe and connect numbers\n", " # to equities via reindexing\n", " df_composite = pd.Series(data=df_composite,index=index)\n", " \n", " # sort descending\n", " df_composite.sort(ascending=False)\n", "\n", " return df_composite\n", "\n", "# compute the standardized values\n", "results_standard, index = standard_frame_compute(results)\n", "\n", "# aggregate the scores\n", "ranked_scores = composite_score(results_standard, index)\n", "\n", "# print the final rankings\n", "ranked_scores" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Stock Choice\n", "\n", "Now that we have ranked our securities, we need to choose a long basket and a short basket. Since we need to keep the ratio 130/30 between longs and shorts, why not have 26 longs and 6 shorts (in the algorithm we will weigh each of these equally, giving us our desired leverage and exposure).\n", "\n", "On the graph below, we plot a histogram of the securities to get a sense of the distribution of scores. The red lines represent the cutoff points for the long and short buckets. One thing to notice is that the vast majority of equities are ranked near the middle of the histogram, whereas the tails are quite thin. This would suggest that there is something special about the securities chosen to be in these baskets, and -hopefully- these special qualities will yield positive alpha for the strategy." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0oAAAHxCAYAAABTSExyAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3XucVQW9///3zDCgXERBQdEyxdDMSCS8cTgcFMeTeaMQ\nicQ8lh3LS95AULycY49M/BXiwzjqUQq8RCrpITVI62gmiH4B8XayRCMvyU1FLiMQzu8PH84jFoyj\nxOw9Ds/n4+HjMXvtvfb6zGa5hxdr7TUVdXV1dQEAAKBeZbkHAAAAaG6EEgAAQIFQAgAAKBBKAAAA\nBUIJAACgQCgBAAAUNHko/eEPf8gRRxyR2267LUny+uuvZ/jw4TnppJNy7rnnZt26dUmSadOmZfDg\nwTnxxBNz1113JUn+9re/5YILLsiwYcMyfPjwvPLKK009LgAAQNOGUm1tba666qr07du3ftn48eMz\nfPjw3HrrrfnkJz+ZqVOnpra2NhMmTMikSZMyefLkTJo0KW+//XbuvffedOzYMbfffntOP/30/PCH\nP2zKcQEAAJI0cSi1adMmN9xwQ3bcccf6ZY8//ngGDBiQJBkwYEBmzpyZ+fPnp2fPnmnXrl3atGmT\nAw44IHPmzMmsWbMycODAJMmhhx6auXPnNuW4AAAASZo4lCorK9O6desNltXW1qa6ujpJ0rlz5yxe\nvDjLli1Lp06d6h/TqVOnLFmyJEuXLq1fXlFRkcrKyvztb39rypEBAADSqpwbr6ur+0jL33333Uaf\nc86cOf/QTAAAQMvXu3fvD7y/5KHUrl27rF27Nq1bt86iRYvStWvXdOnSJUuWLKl/zKJFi9KrV690\n6dIlS5cuzd57711/JKlVq8ZHbuybhi1lzpw5H31/q6hIGvjHAPggm7W/wWayv1FqDe5zfm7SBD7M\nwZWSXx78kEMOyYwZM5IkM2bMSL9+/dKzZ88888wzWblyZVatWpV58+ald+/e6du3b6ZPn54k+e1v\nf5uDDjqo1OMCAABboSY9ojR//vyMGTMmb7zxRqqqqjJlypTcfPPNGTVqVH7+85+nW7duGTRoUKqq\nqnL++efn1FNPTWVlZc4666y0b98+Rx11VB599NEMGzYsbdq0yQ9+8IOmHBcAACBJE4fS5z//+fzy\nl7/caPnEiRM3WlZTU5OampoNllVWVubKK69ssvkAAAA2peSn3gEAADR3QgkAAKBAKAEAABQIJQAA\ngAKhBAAAUCCUAAAACoQSAABAgVACAAAoEEoAAAAFQgkAAKBAKAEAABQIJQAAgAKhBAAAUCCUAAAA\nCoQSAABAgVACAAAoEEoAAAAFQgkAAKBAKAEAABQIJQAAgAKhBAAAUCCUAAAACoQSAABAgVACAAAo\nEEoAAAAFQgkAAKBAKAEAABQIJQAAgAKhBAAAUCCUAAAAClqVewAAaMnWr1+fBQsWlHuMj2zhwoXp\n0KFDk26je/fuqaqqatJtAGwuoQQATWjBggUZPvr2tO3YpdyjfHT3vt5kT716+eLccuWw9OjRo8m2\nAfCPEEoA0MTaduyS9jvsWu4xAPgIfEYJAACgQCgBAAAUCCUAAIACoQQAAFAglAAAAAqEEgAAQIFQ\nAgAAKBBKAAAABUIJAACgQCgBAAAUCCUAAIACoQQAAFAglAAAAAqEEgAAQIFQAgAAKBBKAAAABUIJ\nAACgQCgBAAAUCCUAAIACoQQAAFAglAAAAAqEEgAAQIFQAgAAKBBKAAAABUIJAACgQCgBAAAUCCUA\nAIACoQQAAFAglAAAAAqEEgAAQIFQAgAAKBBKAAAABUIJAACgQCgBAAAUCCUAAIACoQQAAFAglAAA\nAAqEEgAAQIFQAgAAKBBKAAAABUIJAACgQCgBAAAUCCUAAIACoQQAAFAglAAAAAqEEgAAQIFQAgAA\nKGhV6g2uXr06F154YZYvX55169bljDPOyF577ZURI0akrq4uO+20U8aOHZvq6upMmzYtkydPTlVV\nVU444YQMHjy41OMCAABboZKH0t13350999wz5557bhYvXpyvf/3r2X///XPSSSflyCOPzLhx4zJ1\n6tQcd9xxmTBhQqZOnZpWrVpl8ODBqampyXbbbVfqkQEAgK1MyU+969SpU958880kyfLly9OpU6c8\n8cQTOeyww5IkAwYMyMyZMzN//vz07Nkz7dq1S5s2bXLAAQdk7ty5pR4XAADYCpU8lL74xS/m9ddf\nT01NTU4++eRceOGFqa2tTXV1dZKkc+fOWbx4cZYtW5ZOnTrVr9epU6csWbKk1OMCAABboZKfejdt\n2rTsvPPOufHGG/P888/n4osv3uD+urq6Ta7X0HIAAIAtreShNHfu3PTr1y9Jsvfee2fRokXZdttt\ns3bt2rRu3TqLFi1K165d06VLlw2OIC1atCi9evX6UNuYM2dOk8wOm/JR97fem7EOvM++8/GzcOHC\nco/QbD3zzDNZsWJFucegGdnUe5yfm5RLyUNp9913z5NPPpkjjjgir776atq2bZuDDjoo06dPz7HH\nHpsZM2akX79+6dmzZ8aMGZOVK1emoqIi8+bN2+joU0N69+7dxN8FvGfOnDmbtb/ZR9kcm7u/UV4d\nOnRI7n293GM0S/vtt1969OhR7jFoJj7oPc57H1vah4nvkofSiSeemIsuuijDhw/P+vXrc8UVV2SP\nPfbIhRdemDvuuCPdunXLoEGDUlVVlfPPPz+nnnpqKisrc9ZZZ6V9+/alHhcAANgKlTyU2rZtm2uu\nuWaj5RMnTtxoWU1NTWpqakoxFgAAQL2SX/UOAACguRNKAAAABUIJAACgQCgBAAAUCCUAAIACoQQA\nAFAglAAAAAqEEgAAQIFQAgAAKBBKAAAABUIJAACgQCgBAAAUCCUAAIACoQQAAFAglAAAAAqEEgAA\nQIFQAgAAKBBKAAAABUIJAACgQCgBAAAUCCUAAIACoQQAAFAglAAAAAqEEgAAQIFQAgAAKBBKAAAA\nBUIJAACgQCgBAAAUCCUAAIACoQQAAFAglAAAAAqEEgAAQIFQAgAAKBBKAAAABUIJAACgQCgBAAAU\nCCUAAIACoQQAAFAglAAAAAqEEgAAQIFQAgAAKBBKAAAABUIJAACgQCgBAAAUCCUAAIACoQQAAFAg\nlAAAAAqEEgAAQIFQAgAAKBBKAAAABUIJAACgQCgBAAAUCCUAAIACoQQAAFAglAAAAAqEEgAAQIFQ\nAgAAKBBKAAAABUIJAACgQCgBAAAUCCUAAIACoQQAAFAglAAAAAqEEgAAQIFQAgAAKBBKAAAABUIJ\nAACgQCgBAAAUCCUAAIACoQQAAFAglAAAAAqEEgAAQIFQAgAAKBBKAAAABUIJAACgQCgBAAAUCCUA\nAIACoQQAAFAglAAAAAqEEgAAQIFQAgAAKGhVjo1OmzYtN998c1q1apWzzz47e++9d0aMGJG6urrs\ntNNOGTt2bKqrqzNt2rRMnjw5VVVVOeGEEzJ48OByjAsAAGxlSh5Kb731Vn784x/nnnvuyapVq3Lt\ntddm+vTpGT58eGpqajJu3LhMnTo1xx13XCZMmJCpU6emVatWGTx4cGpqarLddtuVemQAAGArU/JT\n72bOnJm+fftm2223zY477pj//M//zOOPP54BAwYkSQYMGJCZM2dm/vz56dmzZ9q1a5c2bdrkgAMO\nyNy5c0s9LgAAsBUq+RGlV199NbW1tfn2t7+dFStW5Iwzzsg777yT6urqJEnnzp2zePHiLFu2LJ06\ndapfr1OnTlmyZEmpxwUAALZCJQ+lurq6+tPvXn311Zx88smpq6vb4P6G1vuw5syZ8w/PCR/WR93f\nem/GOvA++87Hz8KFC8s9QrP1zDPPZMWKFeUeg2ZkU+9xfm5SLo2G0uzZs3PQQQdtsOzBBx/MwIED\nN2uDO+64Y3r16pXKysp84hOfSLt27dKqVausXbs2rVu3zqJFi9K1a9d06dJlgyNIixYtSq9evT7U\nNnr37r1Zs8FHNWfOnM3a3+yjbI7N3d8orw4dOiT3vl7uMZql/fbbLz169Cj3GDQTH/Qe572PLe3D\nxHeDn1F65ZVXMmvWrFx55ZWZNWtW/X+PPPJIvv/972/2UH379s3s2bNTV1eXN998M6tXr84hhxyS\n6dOnJ0lmzJiRfv36pWfPnnnmmWeycuXKrFq1KvPmzfM/CQAAUBINHlFasmRJ7r///rz66quZMGFC\n/fLKysoMHTp0szfYtWvXHHnkkRkyZEgqKipy6aWXZr/99svIkSNzxx13pFu3bhk0aFCqqqpy/vnn\n59RTT01lZWXOOuustG/ffrO3CwAA8GE1GEq9evVKr1690r9//80+za4hQ4YMyZAhQzZYNnHixI0e\nV1NTk5qami26bQAAgMY0ennwffbZJ2effXaGDx+eJLnzzjvz5z//uannAgAAKJtGQ+nSSy/Ncccd\nV3/VuU996lO55JJLmnwwAACAcmk0lNatW5fDDz88FRUVSZI+ffo0+VAAAADl1GgoJcnbb79dH0p/\n+tOfsmbNmiYdCgAAoJwa/T1KZ5xxRoYMGZIlS5bkmGOOyZtvvpmrr766FLMBAACURaOh1KdPn9xz\nzz354x//mNatW2ePPfZwRAkAAGjRGj317vTTT09FRUV69uyZffbZJ08//XQGDx5citkAAADKotFQ\n+uIXv5hvfOMbeeONNzJ+/Phcfvnlueaaa0oxGwAAQFk0eurdl7/85ey888455phjcuCBB+auu+7K\nNttsU4rZAAAAyqLBUBo/fvwGtz//+c/nhRdeyA033JAk+e53v9u0kwEAAJRJg6FUVVW1we199903\n++67b5MPBAAAUG4NhtKZZ55Z//XKlSvTvn37LF26NH/+859zwAEHlGQ4AACAcmj0Yg5XXHFF7r//\n/rz11lsZOnRobr311lx++eUlGA0AAKA8Gg2l5557LkOGDMmvfvWrDBo0KNdcc00WLlxYitkAAADK\notFQqqurS5I89NBDOeyww5Ika9eubdqpAAAAyqjRUNpjjz1y1FFHZdWqVfnMZz6Te+65Jx07dizF\nbAAAAGXR6O9R+t73vpc//vGP6d69e5Jkr732yne+850mHwwAAKBcGg2lJFm8eHGef/75JO+ddnf9\n9dfnt7/9bZMOBgAAUC6NhtKIESOyfPnyPP/88znggAPy5JNP5uyzzy7FbAAAAGXR6GeUFi1alJtv\nvjl77LFHrr322vzsZz/Lk08+WYrZAAAAyqLRUFq/fn3efffd/O1vf8uaNWuy6667ZsGCBaWYDQAA\noCwaPfXu0EMPzc0335yBAwdm0KBB2W233UoxFwAAQNk0Gkpnn3121q9fn6qqqvTq1SvLli1L3759\nSzEbAABAWTR66l2SVFVV5Q9/+EOeeuqptG3bNm3btm3quQAAAMqmwVC67777cuCBB+b444/P73//\n+4waNSp//etfc+211+bGG28s5YwAAAAl1eCpd5MmTcrdd9+d1157Leecc07uu+++bL/99lm3bl2G\nDRuWb33rW6WcEwAAoGQaDKVtttkmu+66a3bdddfstttu2X777ZMk1dXV2WabbUo2IAAAQKl9qM8o\ntWnTZoPbFRUVTTIMAABAc9DgEaUFCxZk5MiRG31dV1eXF198sTTTAQAAlEGDoXTBBRfUf33IIYds\ncN+hhx7adBMBAACUWYOhNGjQoFLOAQAA0Gx8qM8oAQAAbE2EEgAAQEGDp94V1dXVpa6urv52ZaXG\nAgAAWqZGQ+mmm27K9ddfn1WrViV5L5gqKiryf//3f00+HAAAQDk0GkpTp07NtGnT0q1bt1LMAwAA\nUHaNnj+3++67iyQAAGCr0ugRpb333jvnn39+DjzwwFRVVdUvHzx4cJMOBgAAUC6NhtLixYvTunXr\nPPnkkxssF0oAAEBL1WgoXXnllaWYAwAAoNloMJTOOeecXHPNNenfv38qKio2uv+hhx5qyrkAAADK\npsFQGjNmTJLk9ttvL9kwAAAAzUGDobTjjjsmSXbdddeSDQMAANAcNHp5cAAAgK1No6FUV1dXijkA\nAACajUZDacCAARk3blxefvnlUswDAABQdo2G0h133JEddtghI0aMyCmnnJJf/vKXWbt2bSlmAwAA\nKItGQ6lLly455ZRTMmXKlIwaNSo33nhj+vXrl3HjxmXNmjWlmBEAAKCkPtTFHB577LGMGDEi3/nO\nd9K/f//cfvvt2W677fLd7363qecDAAAouQYvD/6+gQMHZrfddsuQIUPy/e9/P9XV1UmS7t2758EH\nH2zyAQEAAEqt0SNKxx9/fH7605/mqKOOqo+kn/3sZ0n8MloAAKBlavCI0nPPPZdnn3029913X3be\neef65evWrcuPf/zjfPWrX01FRUVJhgQAACilBkOpTZs2WbZsWVasWJE5c+bUL6+oqMjIkSNLMhwA\nAEA5NBhK3bt3T/fu3XPwwQdn//33L+VMAAAAZdVgKH3ve9/LmDFjMnbs2E2eYnfbbbc16WAAAADl\n0mAoDR48OElyzjnnlGwYAACA5qDBUNpnn32SJL/4xS/ygx/8YIP7vvGNb+TAAw9s2skAAADKpMFQ\nmjZtWqZMmZI//elP+drXvla/fN26dVm2bFlJhgMAACiHBkPp2GOPzUEHHZQLLrggZ511Vv3yysrK\n7LXXXiUZDgAAoBwaDKUk6dq1a2655ZasWLEib731Vv3yFStWZPvtt2/y4QAAAMrhA0Mpee/qd1On\nTk2nTp1SV1eX5L3fpfSb3/ymyYcDAAAoh0ZDafbs2XnsscfSpk2bUswDAABQdpWNPWD33XcXSQAA\nwFal0SNKO++8c772ta+ld+/eqaqqql/+3e9+t0kHAwAAKJdGQ2n77bfPIYccUopZAAAAmoVGQ+nM\nM8/caNlVV13VJMMAAAA0B42G0qOPPpof/ehH9ZcHX7t2bbbffvtceOGFTT4cAABAOTR6MYdrrrkm\nl1xySTp37pzrr78+X/nKVzJixIhSzAYAAFAWjYZS+/bts//++6e6ujqf/vSnc8455+SnP/1pCUYD\nAAAoj0ZPvVu7dm0ef/zxbLfddrn77rvTvXv3vPbaa6WYDQAAoCwaDaUrrrgiS5cuzciRI+u/Pv30\n00sxGwAAQFk0Gkp77rln9txzzyTJxIkTm3wgAACAcms0lPr375+KioqNlj/00ENNMQ8AAEDZNRpK\nt99+e/3X69aty6xZs7JmzZomHQoAAKCcGg2lXXfddYPbn/rUp/KNb3wjp5xySlPNBAAAUFaNhtKs\nWbM2uP3666/nL3/5S5MNBAAAUG6NhtKECRPqv66oqEj79u3zH//xH006FAAAQDk1Gkq33HJLKeYA\nAABoNio/6M7Zs2fnpJNOSq9evXLQQQfl5JNPzqOPPlp//6pVq5p8QAAAgFJr8IjS9OnTc9111+W8\n887L/vvvnyR5+umnc/XVV2fNmjU57LDDcuaZZ+YnP/lJyYYFAAAohQZDaeLEifnv//7v7LLLLvXL\n+vfvn8985jM599xzs8MOO2Tp0qWbveE1a9bk6KOPzhlnnJGDDz44I0aMSF1dXXbaaaeMHTs21dXV\nmTZtWiZPnpyqqqqccMIJGTx48GZvDwAA4MNq8NS7ioqKDSLpfV26dEltbW1GjBiRyy67bLM3PGHC\nhGy//fZJkvHjx2f48OG59dZb88lPfjJTp05NbW1tJkyYkEmTJmXy5MmZNGlS3n777c3eHgAAwIfV\nYCjV1tY2uNKqVavywAMP5Atf+MJmbfTFF1/MSy+9lP79+6euri5PPPFEBgwYkCQZMGBAZs6cmfnz\n56dnz55p165d2rRpkwMOOCBz587drO0BAAB8FA2GUq9evTZ5xbubbrope++9dyoqKjZ7o2PHjs2o\nUaPqb9fW1qa6ujpJ0rlz5yxevDjLli1Lp06d6h/TqVOnLFmyZLO3CQAA8GE1+BmlESNG5Fvf+lbu\nvffefO5zn0tdXV3mzZuXqqqq3HTTTZu9wXvuuSd9+vRJt27dNnl/XV3dR1q+KXPmzNms2WBzfNT9\nrfdmrAPvs+98/CxcuLDcIzRbzzzzTFasWFHuMWhGNvUe5+cm5dJgKLVv3z633357Zs6cmeeeey5t\n2rTJEUcckYMPPvgf2uDDDz+cV155Jb/+9a+zaNGiVFdXp23btlm7dm1at26dRYsWpWvXrunSpcsG\nR5AWLVqUXr16faht9O7d+x+aET6sOXPmbNb+Zh9lc2zu/kZ5dejQIbn39XKP0Sztt99+6dGjR7nH\noJn4oPc4731saR8mvhv9hbOHHnpoDj300C0yUJKMGzeu/uvrrrsuu+22W+bOnZvp06fn2GOPzYwZ\nM9KvX7/07NkzY8aMycqVK1NRUZF58+bl4osv3mJzAAAANKTRUCqFs88+OyNHjswdd9yRbt26ZdCg\nQamqqsr555+fU089NZWVlTnrrLPSvn37co8KAABsBcoaSmeeeWb91xMnTtzo/pqamtTU1JRyJAAA\ngIavegcAALC1EkoAAAAFQgkAAKBAKAEAABQIJQAAgAKhBAAAUCCUAAAACoQSAABAgVACAAAoEEoA\nAAAFQgkAAKBAKAEAABQIJQAAgAKhBAAAUCCUAAAACoQSAABAgVACAAAoEEoAAAAFQgkAAKBAKAEA\nABQIJQAAgAKhBAAAUCCUAAAACoQSAABAgVACAAAoEEoAAAAFQgkAAKBAKAEAABQIJQAAgAKhBAAA\nUCCUAAAACoQSAABAgVACAAAoEEoAAAAFQgkAAKBAKAEAABQIJQAAgAKhBAAAUCCUAAAACoQSAABA\ngVACAAAoEEoAAAAFQgkAAKBAKAEAABQIJQAAgAKhBAAAUCCUAAAACoQSAABAgVACAAAoEEoAAAAF\nQgkAAKBAKAEAABQIJQAAgAKhBAAAUCCUAAAAClqVewAAYOtT9+67eemll8o9RrPUvXv3VFVVlXsM\n2OoJJQCg5GpXLMmlNy5N244Lyj1Ks7J6+eLccuWw9OjRo9yjwFZPKAEAZdG2Y5e032HXco8BsEk+\nowQAAFAglAAAAAqEEgAAQIFQAgAAKBBKAAAABUIJAACgQCgBAAAUCCUAAIACoQQAAFAglAAAAAqE\nEgAAQEGrcg8AQMuwfv36LFiwoNxjNDsvvfRSuUcAYDMIJQC2iAULFmT46NvTtmOXco/SrCx75f/S\nebfPlHsMAD4ioQTAFtO2Y5e032HXco/RrKxevqjcIwCwGXxGCQAAoEAoAQAAFAglAACAAqEEAABQ\nIJQAAAAKhBIAAECBUAIAACgQSgAAAAVl+YWzY8eOzdy5c7N+/fp861vfyuc+97mMGDEidXV12Wmn\nnTJ27NhUV1dn2rRpmTx5cqqqqnLCCSdk8ODB5RgXAADYypQ8lGbPnp0XXnghU6ZMyVtvvZVBgwbl\n4IMPzkknnZQjjzwy48aNy9SpU3PcccdlwoQJmTp1alq1apXBgwenpqYm2223XalHBgAAtjIlP/Wu\nT58+GT9+fJJku+22y+rVq/PEE0/ksMMOS5IMGDAgM2fOzPz589OzZ8+0a9cubdq0yQEHHJC5c+eW\nelwAAGArVPJQqqyszLbbbpskueuuu/Iv//Ivqa2tTXV1dZKkc+fOWbx4cZYtW5ZOnTrVr9epU6cs\nWbKk1OMCAABbobJdzOHBBx/M1KlTc8kll6Surq5++d9//fcaWg4AALClleViDo888khuvPHG3Hzz\nzWnfvn3atWuXtWvXpnXr1lm0aFG6du2aLl26bHAEadGiRenVq9eHev45c+Y01eiwkY+6v/XejHXg\nfc1531m4cGG5R4AW4ZlnnsmKFSvKPUZZbOo9zs9NyqXkobRy5cpcffXV+elPf5oOHTokSQ455JDM\nmDEjxxxzTGbMmJF+/fqlZ8+eGTNmTFauXJmKiorMmzcvF1988YfaRu/evZvyW4B6c+bM2az9zT7K\n5tjc/a1UOnTokNz7ernHgI+9/fbbLz169Cj3GCX3Qe9xzfm9j4+nDxPfJQ+l+++/P2+99VbOOeec\n1NXVpaKiIldddVUuvvji/PznP0+3bt0yaNCgVFVV5fzzz8+pp56aysrKnHXWWWnfvn2pxwUAALZC\nJQ+lIUOGZMiQIRstnzhx4kbLampqUlNTU4qxAAAA6pXtYg4AAADNlVACAAAoEEoAAAAFQgkAAKBA\nKAEAABQIJQAAgAKhBAAAUCCUAAAACoQSAABAgVACAAAoEEoAAAAFQgkAAKBAKAEAABQIJQAAgAKh\nBAAAUCCUAAAACoQSAABAgVACAAAoEEoAAAAFQgkAAKBAKAEAABQIJQAAgAKhBAAAUCCUAAAACoQS\nAABAgVACAAAoEEoAAAAFQgkAAKBAKAEAABQIJQAAgAKhBAAAUCCUAAAACoQSAABAgVACAAAoEEoA\nAAAFQgkAAKBAKAEAABQIJQAAgAKhBAAAUCCUAAAACoQSAABAgVACAAAoEEoAAAAFQgkAAKBAKAEA\nABQIJQAAgAKhBAAAUCCUAAAACoQSAABAgVACAAAoEEoAAAAFQgkAAKCgVbkHAADgPXXvvpuXXnqp\n3GOUxcKFC9OhQ4eNlvdIsn79+lRVVZV+KLZqQgkAoJmoXbEkl964NG07Lij3KOVx7+sbLfrfJAsW\nLEiPHj1KPw9bNaEEANCMtO3YJe132LXcY8BWz2eUAAAACoQSAABAgVACAAAoEEoAAAAFQgkAAKBA\nKAEAABQIJQAAgAKhBAAAUCCUAAAACoQSAABAgVACAAAoEEoAAAAFQgkAAKBAKAEAABQIJQAAgAKh\nBAAAUCCUAAAACoQSAABAgVACAAAoEEoAAAAFrco9AMDH0fr167NgwYKSbnPhwoXp0KFDSbf5Ubz0\n0kvlHgFooby/bFr37t1TVVVV7jFaLKEEsBkWLFiQ4aNvT9uOXUq74XtfL+32PoJlr/xfOu/2mXKP\nAbRAl944K207lvYfp5q71csX55Yrh6VHjx7lHqXFEkrAByrHkZOPg5deeiltO3ZJ+x12Lfcozcbq\n5YvKPQLQQnm/pRyEEvCBynbkpJlz9AQAWjahBDTKv+RtzNETAGjZXPUOAACgoNkfUbryyiszf/78\nVFRU5KKJv1FuAAANh0lEQVSLLsrnPve5co9EC7U5n8XZnKuQ9Ujyxz/+8SOtU06uNAQAbI2adSg9\n8cQTWbhwYaZMmZIFCxbk4osvzpQpU8o9Fi3UZn8W5yNehex/k/z7Dx78aNsoI5/FAYDmp+7dd/1j\nZgO21GXTm3UozZo1KwMHDkzy3jf89ttvZ9WqVWnXrl2ZJ/v4Gzdhcv78+opyj9GsvLlsUdp23Lkk\nn8X5OH3ex2dxAKD5qV2xJJfeuNRl0wu25GXTm3UoLV26NPvtt1/97R122CFLly4VSlvAn19+LS8t\nebfcYzQrK5evzOp3F5dmW2++WpLtbAm1K95IUlHuMZodr8vGvCab5nXZNK/LpnldNm318tL8fP44\nqV3xRrbt0LncY7RozTqUiurq6j7U4+bMmdPEk3z8nTz4iHKPsNWac8b/y/9X7iE+koPKPUAz5XXZ\nmNdk07wum+Z12TSvS9GcM/5fJpR7iGbJvtKQFStWbJEeaNah1KVLlyxdurT+9uLFi7PTTjt94Dq9\ne/du6rEAAIAWrllfHrxv376ZMWNGkuTZZ59N165d07Zt2zJPBQAAtHTN+ohSr1698tnPfjZDhw5N\nVVVVLr300nKPBAAAbAUq6j7sB38AAAC2Es361DsAAIByEEoAAAAFQgkAAKCgRYXSG2+8kdNOOy0n\nn3xyhg0blqeeeqrcI9HCrV+/PqNGjcqwYcMydOjQzJ07t9wj0cLNnj07hx56aB5++OFyj0ILduWV\nV2bo0KH56le/mqeffrrc47AV+MMf/pAjjjgit912W7lHYSswduzYDB06NCeccEIeeOCBBh/XrK96\n91FNmzYtxx9/fL70pS/liSeeyPjx43PzzTeXeyxasP/5n//JNttsk9tvvz0vvPBCRo8enTvvvLPc\nY9FC/eUvf8ktt9ySL3zhC+UehRbsiSeeyMKFCzNlypQsWLAgF198caZMmVLusWjBamtrc9VVV6Vv\n377lHoWtwOzZs/PCCy9kypQpeeuttzJo0KAcccQRm3xsizqidMopp+RLX/pSkuS1117LzjvvXOaJ\naOmOPfbYjB49OknSqVOnLF++vMwT0ZLtvPPOue6669KuXbtyj0ILNmvWrAwcODBJ0r1797z99ttZ\ntWpVmaeiJWvTpk1uuOGG7LjjjuUeha1Anz59Mn78+CTJdtttl9ra2jR0EfAWdUQpSZYuXZrTTz89\nq1evzqRJk8o9Di1cq1at0qrVe/8bTZo0KUcffXSZJ6Ila926dblHYCuwdOnS7LfffvW3d9hhhyxd\nulSg02QqKyu9v1EylZWV2XbbbZMkd955Z/r375+KiopNPvZjG0p33nln7rrrrlRUVKSuri4VFRU5\n66yz0rdv39x111353e9+l1GjRjn1ji3mg/a52267Lc8991yuv/76co9JC/FB+xuUkl+3CLREDz74\nYH7xi198YCt8bEPphBNOyAknnLDBsscffzzLly9Px44d88///M8ZOXJkmaajJdrUPpe89xfahx56\nKBMmTEhVVVUZJqMlamh/g6bWpUuXLF26tP724sWLs9NOO5VxIoAt65FHHsmNN96Ym2++Oe3bt2/w\ncS3qM0oPPPBA7rnnniTJ888/n27dupV5Ilq6l19+OT//+c9z3XXXpbq6utzjsBXxr/w0lb59+2bG\njBlJkmeffTZdu3ZN27ZtyzwVwJaxcuXKXH311bn++uvToUOHD3xsRV0L+mn75ptvZtSoUVm9enXW\nrl2biy++OD179iz3WLRg48aNy/33359ddtml/vSoiRMn1n9uCbakBx54INdee20WL16cdu3aZYcd\ndsjUqVPLPRYt0I9+9KM8/vjjqaqqyqWXXpq999673CPRgs2fPz9jxozJG2+8kaqqqnTs2DG33npr\nOnbsWO7RaIHuuOOOXHfddfnUpz5V/3e3sWPHbvIicC0qlAAAALaEFnXqHQAAwJYglAAAAAqEEgAA\nQIFQAgAAKBBKAAAABUIJAACgQCgBsEkPP/xwTjrppHz961/PCSeckPPOOy8rV65MksybNy+vvPLK\nFtlO//7989prr/3D6z/yyCO54YYb/uF5RowYUf/Ly//eU089lVNOOSVf//rXM3To0Jx22mn561//\n+g9vD4DmSSgBsJF169Zl5MiRGT9+fCZNmpQ777wzu+yyS+68884kyS9+8Yu8/PLLW2RbFRUVW2T9\nfv365d///d+3xEibNGLEiIwaNSqTJk3KlClT0r9///zkJz9psu0BUF6tyj0AAM3PmjVr8s4772TV\nqlXp3LlzkvdCIUkefPDBTJ8+PU8//XRGjx6dVq1a5eqrr84222yTd955J5dddlk+85nPZPTo0enS\npUuef/75LFy4MF/5ylfyzW9+M8uWLcs555yTd999N/vuu2/e/73ntbW1ufDCC/PWW2+ltrY2NTU1\nOe200/L4449nwoQJ2WabbXL44YfnsMMO2+T6d999d2bOnJnzzjsvI0eOTEVFRerq6jJv3rzcfvvt\n6dmzZ8aNG5e5c+dmzZo16dOnT0aMGJG6urpcdNFF+dOf/pRu3bpl9erVm3xNli9fnhUrVtTfPumk\nk+q/XrhwYcaMGZMkad26da688sp06dIlEyZMyMMPP5zq6up8+tOfzpgxY/L666/n9NNPz957753u\n3bvn29/+9ibnWrx4cS644IL6P48TTzwxX/7yl7fwnzQADRFKAGykffv2OfPMM3PcccelV69eOfDA\nA3PkkUdmjz32yMCBAzNp0qScccYZOeigg/Kb3/wml19+efbZZ5/cd999uf766zN+/PgkySuvvJLr\nr78+r732Wo499th885vfzOTJk7P//vvn/PPPz3PPPZdbb701SbJs2bIcdthhOf7447N27doceuih\nGTZsWJLk2WefzW9/+9t06NAh48aN2+T6yXtHl3bZZZfccsstSZLbbrstu+yyS3r27Jnp06dn8eLF\n9fedeeaZeeihh1JdXZ2XXnopd911V955550MHDgwRx999EavyejRo/Ptb387PXr0yIEHHpiamprs\nu+++SZLLLrssp512Wv75n/85999/f6ZPn56ePXvmwQcfzF133ZXKysqcffbZ+eUvf5k+ffrkxRdf\nzHXXXZfdd999k3P97//+bxYuXJju3bvnsssuy9q1a3PHHXc00Z82AJsilADYpNNOOy1DhgzJo48+\nmsceeywnnnhizjvvvAwdOjRJ6o/k7Ljjjrn66quzZs2arFixIh07dqx/jgMPPDBJ0q1bt6xatSp1\ndXV5/vnn659j3333Tfv27ZMknTt3zty5czNlypRUV1dn7dq1Wb58eZJkjz32SIcOHZJko/XfX140\nb9683H333bntttuSJLNnz868efNy8sknp66uLqtWrcorr7ySdevWpVevXkmSbbbZJp///Oc3+XzH\nHXdcampqMnPmzDz22GM57bTTMnjw4Jx77rmZP39+/fd61FFHJUkmTZqUPn36pLLyvbPcDzrooDzz\nzDPp06dPtt9+++y+++4NzvXqq6+mf//+Of300zN69Oj079+//nsGoDSEEgCb9M4776Rjx4456qij\nctRRR+Vf//Vfc9VVV230F/aRI0fmiiuuyIEHHpiHHnooEydOrL+vqqpqg8e+H1d//7mk9evXJ3kv\nLNatW5cpU6YkSQ4++OD6x1RXV2/wPH+//t/+9reNZl+6dGkuvfTS/Nd//VfatGmT5L1T4k488cT8\n27/92waPnThxYn3M/P08m3o9tt122xx++OE5/PDDc9JJJ+UrX/lKzj333FRUVOTdd99tcMa//96L\n309DcyXJ/fffn8cffzy/+tWvMmnSpPzsZz/b5GwAbHku5gDARn7/+99nyJAh9Ve5S5KXX365/ihI\nZWVlfaAsW7Yse+21V9avX59f/epXWbt27Saf8/1Q6N69e+bNm5ckmT9/fmpra5O8Fzfdu3dPkvzm\nN7/JmjVrNvlcDa3/vvXr1+e8887LBRdckN12261+ee/evfPrX/+6PoR+/OMf5y9/+Uu6d++e+fPn\nJ0lWrlyZp556aqNtvvjii6mpqcmiRYs2eD0++clPJkkOOOCAPPLII0mSe++9t/70wNmzZ9dvb9as\nWdl///03eC0+aK577703Tz31VA455JBcfvnlef311zeKMQCajiNKAGzkn/7pn7Jw4cKccsopadu2\nberq6rLjjjvm0ksvTZL07ds3l112WS666KKcdtppOfnkk9O1a9ecdtppGTVqVCZPnrzRc75/hOXk\nk0/OOeeck1NOOSV77bVXPvGJTyRJBg8enPPOOy+/+93vcthhh+WYY47JBRdckAsvvHCD52lo/ffN\nmDEjzz77bG6++ebcdNNNqaioyFe/+tV88YtfzPz58zN06NBUVVXls5/9bD7xiU9kt912y7333psh\nQ4akW7du9afh/b0999wzo0ePztlnn53WrVunsrIy22yzTX74wx8mSS655JJccsklufXWW1NdXZ0r\nr7wyXbt2zVFHHZVhw4alqqoq++67b44++ui8+uqrGxxtqqmp2eRcq1evzmWXXZbWrVsnee9UyL8/\n8gVA06qo+/t/1gIAAMCpdwAAAEVCCQAAoEAoAQAAFAglAACAAqEEAABQIJQAAAAKhBIAAEDB/w/n\nA6IarhW3RQAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# create histogram of scores\n", "ranked_scores.hist()\n", "\n", "# make scores into list for ease of manipulation\n", "ranked_scores_list = ranked_scores.tolist()\n", "\n", "# add labels to axes\n", "plt.xlabel('Standardized Scores')\n", "plt.ylabel('Quantity in Basket')\n", "\n", "# show long bucket\n", "plt.axvline(x=ranked_scores_list[25], linewidth=1, color='r')\n", "\n", "# show short bucket\n", "plt.axvline(x=ranked_scores_list[-6], linewidth=1, color='r');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Please see the full algorithm for backtested returns!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "NB: In the implementation of the algorithm, a series of filters is used in order to ensure that only tradeable stocks are included. The methodology for this filter can be found in https://www.quantopian.com/posts/pipeline-trading-universe-best-practice." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*This presentation is for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation for any security; nor does it constitute an offer to provide investment advisory or other services by Quantopian, Inc. (\"Quantopian\"). Nothing contained herein constitutes investment advice or offers any opinion with respect to the suitability of any security, and any views expressed herein should not be taken as advice to buy, sell, or hold any security or as an endorsement of any security or company. In preparing the information contained herein, Quantopian, Inc. has not taken into account the investment needs, objectives, and financial circumstances of any particular investor. Any views expressed and data illustrated herein were prepared based upon information, believed to be reliable, available to Quantopian, Inc. at the time of publication. Quantopian makes no guarantees as to their accuracy or completeness. All information is subject to change and may quickly become unreliable for various reasons, including changes in market conditions or economic circumstances.*" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.12" } }, "nbformat": 4, "nbformat_minor": 0 }