{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "#Long-Short Equity Strategies\n", "\n", "By Delaney Granizo-Mackenzie\n", "\n", "Part of the Quantopian Lecture Series:\n", "\n", "* [www.quantopian.com/lectures](https://www.quantopian.com/lectures)\n", "* [https://github.com/quantopian/research_public](https://github.com/quantopian/research_public)\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Long-short equity refers to the fact that the strategy is both long and short in the equity market. This is a rather general statement, but has over time grown to mean a specific family of strategies. These strategies rank all stocks in the market using some model. The strategy then goes long (buys) the top $n$ equities of the ranking, and goes short on (sells) the bottom $n$ while maintaining equal dollar volume between the long and short positions. This has the advantage of being statistically robust, as by ranking stocks and entering hundreds or thousands of positions, you are making many bets on your ranking model rather than just a few risky bets. You are also betting purely on the quality of your ranking scheme, as the equal dollar volume long and short positions ensure that the strategy will remain market neutral (immune to market movements)." ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "##Ranking Scheme\n", "\n", "A ranking scheme is any model that can assign each stocks a number, where higher is better or worse. Examples could be value factors, technical indicators, pricing models, or a combination of all of the above. The Ranking Universes by Factors lecture will cover ranking schemes in more detail. Ranking schemes are the secret sauce of any long-short equity strategy, so developing them is nontrivial." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Making a Bet on the Ranking Scheme" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once we have determined a ranking scheme, we would like to be able to profit from it. We do this by investing an equal amount of money long into the top of the ranking, and short into the bottom. This ensures that the strategy will make money proportionally to the quality of the ranking only, and will be market neutral." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###Long and Short Baskets\n", "\n", "If you are ranking $m$ equities, have $d$ dollars to invest, and your total target number of positions to hold is $2n$, then the long and short baskets are created as follows. For each equity in spots $1, \\dots, n$ in the ranking, sell $\\frac{1}{2n} * d$ dollars of that equity. For each equity in spots $m - n, \\dots, m$ in the ranking, buy $\\frac{1}{2n} * d$ dollars of that equity. \n", "\n", "####Friction Because of Prices\n", "\n", "Because equity prices will not always divide $\\frac{1}{2n} * d$ evenly, and equities must be bought in integer amounts, there will be some imprecision and the algorithm should get as close as it can to this number. Most algorithms will have access to some leverage during execution, so it is fine to buy slightly more than $\\frac{1}{2n} * d$ dollars per equity. This does, however, cause some friction at low capital amounts. For a strategy running $d = 100000$, and $n = 500$, we see that \n", "$$\\frac{1}{2n} * d = \\frac{1}{1000} * 100000 = 100$$\n", "This will cause big problems for expensive equities, and cause the algorithm to be overlevered. This is alleviated by trading fewer equities or increasing the capital, $d$. Luckily, long-short equity strategies tend to be very high capicity, so there is for most purposes no ceiling on the amount of money one can invest. For more information on algorithm capacities, refer to the algorithm capacity lecture when it is released." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###Returns Come From The Ranking Spread\n", "\n", "The returns of a long-short equity strategy are dependent on how well the ranking spreads out the high and low returns. To see how this works, consider this hypothetical example." ] }, { "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" ] }, { "cell_type": "code", "execution_count": 17, "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Factor Value
Equity 01.894223
Equity 1-0.211479
Equity 2-0.391872
Equity 30.027782
Equity 40.524842
Equity 5-0.573875
Equity 6-0.452927
Equity 7-1.785987
Equity 8-0.384685
Equity 9-0.716920
\n", "
" ], "text/plain": [ " Factor Value\n", "Equity 0 1.894223\n", "Equity 1 -0.211479\n", "Equity 2 -0.391872\n", "Equity 3 0.027782\n", "Equity 4 0.524842\n", "Equity 5 -0.573875\n", "Equity 6 -0.452927\n", "Equity 7 -1.785987\n", "Equity 8 -0.384685\n", "Equity 9 -0.716920" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# We'll generate a random factor\n", "current_factor_values = np.random.normal(0, 1, 10000)\n", "equity_names = ['Equity ' + str(x) for x in range(10000)]\n", "# Put it into a dataframe\n", "factor_data = pd.Series(current_factor_values, index = equity_names)\n", "factor_data = pd.DataFrame(factor_data, columns=['Factor Value'])\n", "# Take a look at the dataframe\n", "factor_data.head(10)" ] }, { "cell_type": "code", "execution_count": 18, "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", " \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", "
ReturnsFactor Value
Equity 01.9175941.894223
Equity 10.298692-0.211479
Equity 21.002879-0.391872
Equity 31.2848680.027782
Equity 41.1598110.524842
Equity 5-2.483890-0.573875
Equity 61.647554-0.452927
Equity 7-1.889101-1.785987
Equity 8-0.121327-0.384685
Equity 90.190503-0.716920
\n", "
" ], "text/plain": [ " Returns Factor Value\n", "Equity 0 1.917594 1.894223\n", "Equity 1 0.298692 -0.211479\n", "Equity 2 1.002879 -0.391872\n", "Equity 3 1.284868 0.027782\n", "Equity 4 1.159811 0.524842\n", "Equity 5 -2.483890 -0.573875\n", "Equity 6 1.647554 -0.452927\n", "Equity 7 -1.889101 -1.785987\n", "Equity 8 -0.121327 -0.384685\n", "Equity 9 0.190503 -0.716920" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Now let's say our future returns are dependent on our factor values\n", "future_returns = current_factor_values + np.random.normal(0, 1, 10000)\n", "\n", "returns_data = pd.Series(future_returns, index=equity_names)\n", "returns_data = pd.DataFrame(returns_data, columns=['Returns'])\n", "# Put both the factor values and returns into one dataframe\n", "data = returns_data.join(factor_data)\n", "# Take a look\n", "data.head(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now that we have factor values and returns, we can see what would happen if we ranked our equities based on factor values, and then entered the long and short positions." ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0MAAAHxCAYAAACvXWe4AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3X2Q1nW9//HXIi73IpJwTMP1AGsUxzJoLHVC8eY4GWZo\nzYmTFpp0PBPem6H5I40RtfL+fjDHg5bpEW/RpqOmnqz0uGaE0aTnsCipIJLcw3Kzvz/ITZN72f0u\nfB6PGWe4rr34ft6LfOfiud+bq6a5ubk5AAAAhelQ9QAAAABVEEMAAECRxBAAAFAkMQQAABRJDAEA\nAEUSQwAAQJE6VrXwihUr8pWvfCVNTU1ZuXJlDjnkkJx55plVjQMAABSmpsrPGVq2bFm6dOmSVatW\nZdSoUfnWt76VoUOHVjUOAABQkEpPk+vSpUuSZOXKlVm9enV23nnnKscBAAAKUmkMrVmzJp///Oez\n//77Z7/99suAAQOqHAcAAChIpafJvW3RokU58cQTc+aZZ2a//fZb52saGhraeCoAAGBbM2TIkE1+\nbWU3UHinHj16ZNiwYZk+ffp6YyjZvG8MtlcNDQ32Bfgr+wOsZV+AtTb3AEplp8nNnz8/CxcuTJIs\nX748v/rVr/KRj3ykqnEAAIDCVHZk6I033si3v/3trFmzpuXaoU9/+tNVjQMAABSmshjae++9c889\n91S1PAAArWzNmjVpamqqegy2U7W1tenQ4f2d6Fbp3eQAANh+NTU1ZcWKFVWPwXZoxYoVWyW028UN\nFAAA2D516tQpnTt3rnoMWCdHhgAAgCKJIQAAoEhOkwMAoE00NTWlsbFxq26zrq4utbW1W3WblEMM\nAQDQJhobG3PcuB+na88+W2V7SxfMzeSJo1JfX7/B1w0aNCh77713Vq9enT333DOXXHJJunXrtt7X\nP/LII9lrr73Sv3//rTLn+zF//vx84xvfyOrVq3Peeee968N1jzvuuLzxxhst12TtueeeufLKKzd7\njX333Te//e1vN/iaKVOm5NJLL80//MM/ZNWqVfnHf/zHXHrppZt9PdjTTz+dW265JTfccMMmvf6e\ne+7JAQcckD59ts7fmb8nhgAAaDNde/ZJ9167t+manTt3zr333psk+fa3v52f/vSnOeGEE9b7+kce\neSQHH3zwZsXQqlWr0rHj1v+n9a9//evsvffemTBhwjq//sMf/jAf/ehHt/q6f6+mpiaf+9zn8p3v\nfCdJcuaZZ+ahhx7KyJEjW3XdKVOmZODAgWIIAADer49//OP54x//mCR5+eWXc+GFF2b+/Pnp0qVL\nvve97+Wtt97KL37xi/zP//xPbrjhhlx11VU599xzc84552Tw4MGZP39+jj322Dz22GOZMmVKfv7z\nn2fZsmVZs2ZNRo4cmUcffTTLly/PK6+8kkMPPTRnn312y1GdF154IUlyzDHH5Gtf+9q75po9e3bO\nPffcvPXWW9lll10yceLEvPXWW/nBD36Q5cuXZ/r06fnpT3+aTp06vev3NTc3v+d7fOyxx3LDDTdk\n5cqV2XnnnfODH/wgvXv3zpIlSzJhwoRMnz49NTU1GTt2bA477LAkyeWXX57HH388nTt3znXXXZfe\nvXu/Z7tvr7Vq1aosW7YsPXv23OB6zzzzTC666KIka2Pqtttue9f2pk2blvHjx+eqq67KggULcskl\nl2TJkiXp1atXLr744jQ0NGT69Ok566yz0qVLl9xxxx3v+f7fLzEEAEARVq9enaeeeiqf+tSnkiTn\nn39+Lrzwwuy555753e9+lwsuuCC33nprhg8fnoMPPjiHH354y++tqalZ5zZnzJiRBx54IDvttFOm\nTJmSP/7xj7n33ntTW1ubI444Iscdd1zmzZuXuXPn5oEHHkiSLFq06D3bmTBhQkaOHJmjjz46d999\ndyZMmJBrr702p5xySl544YWWIzJ/76yzzmo5Ve2AAw7I2WefnaFDh+bOO+9Mktx1112ZNGlSzjnn\nnFx33XXZaaedWuZYuHBhkmTZsmXZd999c/rpp+f73/9+7rzzzpx88snvWqe5uTkPPfRQGhoa8sYb\nb2SvvfbKwQcfnCTrXe9HP/pRxo8fn3333TfLli1717Vdzz33XCZMmJDrr78+vXv3ztlnn53rr78+\nvXr1ykMPPZTLL788F110UW6//fZ8+9vfbrWjX2IIAIDt2ooVK3L00Udnzpw52X333fPlL385S5Ys\nyfPPP59TTz215XUrV65s+fW6jrisy/7775+ddtopydpg+vSnP53u3bsnSfr3759XX301AwYMyCuv\nvJIJEyZk2LBhOfDAA9+zneeffz7XXnttkuSoo47K97///ZY5NjTLuk6Te+2113LaaafljTfeyMqV\nK/OhD30oydpT7q644oqW170994477piDDjooSfLRj340v/rVr96zTk1NTY488siWKLvgggsyadKk\njBkzZr3rfeITn8jEiRMzYsSIHH744enbt2+S5H//938zfvz4/OhHP8quu+6aP/3pT3nxxRczevTo\nJGuj9Z2nxW3q/4stIYYAANiuderUKffee2+WL1+eE088MY8++mg+/elPp0ePHi3XEv29dx4J6tix\nY9asWZNk7R3x3qlr167vevzOox877LBDVq9enZ122in33XdffvnLX+aOO+7Iww8/3HL62DttrX/0\nT5gwISeccEIOPvjgPPPMM7n66qs3uMY7r3Xq0KFDVq9evc7tvvP3HnTQQbn99tszZsyY9a43ZsyY\nHHzwwXn88cfz5S9/OZMmTUpNTU123XXXNDU15Q9/+EOGDRuW5ubmDBw4MHfcccc6113fUbmtwecM\nAQDQZpYumJvFf/nzVvlv6YK5m7V2586d853vfCeXX355unXrlj322CM/+9nPkqz9h/7b1xJ169Yt\nixcvbvl9u+++e6ZPn54kLa9fl3WFRnNzc/7yl79kzZo1Ofzww3PqqafmD3/4w3tet++++2bq1KlJ\nkgceeCCf/OQnN+l7Wteaixcvbjmycs8997Q8f8ABB+T2229vefz2aXJbss5zzz2Xfv36bXC9l19+\nOQMHDsxJJ52UwYMHZ+bMmUnWHpG68cYb88Mf/jDPPPNM9tprr8yfPz/PP/98krVH6F566aUk7/1/\nsbU5MgQAQJuoq6vL5Imjtvo2N+adRxYGDRqUfv365eGHH84PfvCDfPe7383111+fVatW5cgjj8yH\nP/zhfPazn83555+f2267LVdeeWVOOOGEnHbaabnzzjszbNiwlu3V1NS8a9t///jt5+bMmZNzzz23\n5ejSmWee+Z4Zzz///IwbNy4333xzevfunYkTJ653m+/0zmuGdtlll/zoRz/KN7/5zZx66qnZaaed\n8qlPfSp//vOfkyQnn3xyLrzwwowYMSIdOnTI2LFjc+ihh77ne1jfn+Hb1wytWbMmu+22W8uM61vv\nP/7jP/L000+npqYmAwcOzGc+85mWW3j37t07N954Y0466aRcdNFFueqqqzJhwoQsWrQoq1evzle/\n+tUMGDAgI0eOzPjx41vtBgo1za15Et5W1NDQ8K77qkOp7AvwN/YHWKu97gvLly9Pks3+LBrYmPX9\n3drcfcFpcgAAQJHEEAAAUCQxBAAAFMkNFAAAaDUrVqyoegS2QytWrNgqN1MQQwAAtIp3fuYObE2d\n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\nULBKYqh79+4tv166dGl69epVxRgAAEDBKjlNLkkuv/zy3HfffencuXPuvPPOqsYAAAAKVdPc3Nzc\nGhsePXpSv5RoAAAH/klEQVR05s2b957nTz/99AwfPrzl8U033ZSZM2dm4sSJG9xeQ0PDVp8RAADY\nvgwZMmSTX9tqMbSpXn311YwZMyYPPvhglWMAAACFqeSaocbGxpZfP/rooxk0aFAVYwAAAAWr5Jqh\nyy67LDNnzkyHDh3Sr1+/fPe7361iDAAAoGCVnyYHAABQhUpOkwMAAKiaGAIAAIokhgAAgCJV9qGr\nm+rJJ5/MRRddlDVr1uTYY4/NmDFjqh4JKjN8+PB069YtO+ywQzp27Jj//M//rHokaBPjxo3LE088\nkd69e+eBBx5Ikrz11ls5/fTT8+qrr2b33XfPFVdckZ122qniSaF1rWtfuPrqq3PXXXdll112SZKc\nccYZ+cxnPlPlmNAmXnvttXzrW9/K/PnzU1NTky996Us5/vjjN+v9oV3fQGH16tU54ogjcsstt6Rv\n37459thjc9lll6V///5VjwaVGD58eKZMmZKdd9656lGgTT377LPp2rVrzjnnnJZ/AF566aXp1atX\nTjrppNx0001ZuHBhzjrrrIonhda1rn3hmmuuSbdu3TJ69OiKp4O29cYbb2TevHkZNGhQlixZkpEj\nR+a6667L3XffvcnvD+36NLlp06alX79+2WOPPbLjjjvmyCOPzKOPPlr1WFCpdvzzC2g1Q4cOfc9P\n9R577LF84QtfSJJ84QtfyCOPPFLFaNCm1rUvJN4bKNOuu+7a8nml3bp1S//+/TNnzpzNen9o1zE0\nZ86c7Lbbbi2P+/btmzlz5lQ4EVSrpqYmo0ePzsiRI3PnnXdWPQ5U6s0338wHPvCBJMkHPvCBvPnm\nmxVPBNW57bbbctRRR+Xcc8/NwoULqx4H2tzs2bMzY8aM7LPPPpv1/tCuY6impqbqEaBd+clPfpJ7\n7703kyZNyu23355nn3226pGgXaipqfGeQbG+/OUv59FHH819992XXXfdNRdffHHVI0GbWrJkSU45\n5ZScd9556d69+7u+trH3h3YdQ3379s1rr73W8vj1119P3759K5wIqtWnT58kyS677JLDDjss06ZN\nq3giqE7v3r3zxhtvJEnmzp3bcvE4lKZ3794t/+D74he/mN///vdVjwRtZuXKlTnllFNy1FFH5dBD\nD02yee8P7TqGBg8enFmzZmX27NlpamrKQw89lEMOOaTqsaASy5Yty+LFi5MkS5cuzS9/+cvU19dX\nPBVUZ/jw4bnnnnuSJPfee2/LmyCUZu7cuS2/fuSRR7w3UIzm5uacd9556d+/f772ta+1PL857w/t\n+m5ySfLEE0+869ba3/jGN6oeCSrxyiuv5Jvf/GaStXdaHDFihP2BYpxxxhl55pln8tZbb6V37945\n5ZRTcsghh+S0007La6+95tbaFOPv94WxY8fmmWeeyYwZM1JTU5M99tgjF154Ycv1ErA9e/bZZ/OV\nr3wle++9d8upcGeccUb22WefTX5/aPcxBAAA0Bra9WlyAAAArUUMAQAARRJDAABAkcQQAABQJDEE\nAAAUSQwBAABF6lj1AACUZ/jw4enUqVM6deqUFStWZOjQoRk/fnw6dtz8t6UPf/jD+e1vf5suXbps\n0usXLVqUO+64IyeddNJmrwXA9sWRIQAqcfXVV+fee+/N1KlT8+KLL+bnP/95m6y7YMGC3HzzzW2y\nFgDtmyNDAFTi7c/8Xr58eZqamrLzzjvn17/+da688sqsWLEiq1atysknn5zPfvazSZJrrrkmU6dO\nTadOnVJTU5PJkyene/fuLdtbs2ZNLr744rz55puZOHFiZsyYkR/+8IdZvHhxkuTUU0/NsGHDcuGF\nF2bRokU5+uij06VLl/zkJz9p+28egHahpvntdyMAaCPvPE3u5ZdfzoEHHpirrroqCxcuTPfu3dOh\nQ4fMmzcvxxxzTB588MGsXr06hx12WJ566qnU1tZm6dKl6dSpU3bYYYd8+MMfzq9//euMHz8+H/rQ\nh3L22Wdn4cKF+epXv5qbbropu+66a+bOnZsvfvGLmTp1ahYsWJBjjjkmv/nNb6r+YwCgYo4MAVCJ\nq6++OgMGDEhTU1PGjh2bW2+9NZ/5zGcybty4vPzyy9lhhx2yYMGCzJw5M4MHD06/fv1y9tln58AD\nD8xBBx2Url27tmzr61//eo488siccMIJSZLf/va3mT179ruuC+rQoUNmzZqVnj17tvn3CkD7JIYA\nqFRtbW0OOuigPP744/nFL36RQw45JNdee22S5J//+Z+zYsWKdOjQIXfeeWeee+65/OY3v8nIkSNz\n8803p76+Pkmy33775b//+78zatSodO7cOUmy995757bbbnvPerNnz267bw6Ads0NFACoxNtnaa9Z\nsybPPPNM6urqsnDhwnzwgx9Mkjz11FN5+eWXkyRLlizJm2++mU9+8pMZO3Zs6uvr8+KLL7Zsa+zY\nsdl///1z4oknZvHixfn4xz+exsbGPP300y2vmTZtWpKke/fuWb58eVavXt1W3yoA7ZRrhgBoc++8\nZmjlypWpr6/PhRdemN///ve54IIL0qVLl/zTP/1Tpk+fnnPPPTf9+vXL2LFjs3z58jQ3N+ejH/1o\nLrzwwtTW1mbQoEF57rnn0qVLl0yePDn3339/br755syaNSuXXnppFi5cmJUrV6Zfv3654YYbkiTn\nn39+Ghoa0rNnTzdQACiYGAIAAIrkNDkAAKBIYggAACiSGAIAAIokhgAAgCKJIQAAoEhiCAAAKJIY\nAgAAivT/AXhALcviTVtZAAAAAElFTkSuQmCC\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Rank the equities\n", "ranked_data = data.sort('Factor Value')\n", "\n", "# Compute the returns of each basket\n", "# Baskets of size 500, so we create an empty array of shape (10000/500)\n", "number_of_baskets = 10000/500\n", "basket_returns = np.zeros(number_of_baskets)\n", "\n", "for i in range(number_of_baskets):\n", " start = i * 500\n", " end = i * 500 + 500 \n", " basket_returns[i] = ranked_data[start:end]['Returns'].mean()\n", "\n", "# Plot the returns of each basket\n", "plt.bar(range(number_of_baskets), basket_returns)\n", "plt.ylabel('Returns')\n", "plt.xlabel('Basket')\n", "plt.legend(['Returns of Each Basket']);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's compute the returns if we go long the top basket and short the bottom basket." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "4.036146916686965" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "basket_returns[number_of_baskets-1] - basket_returns[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###Market Neutrality is Built-In\n", "\n", "The nice thing about making money based on the spread of the ranking is that it is unaffected by what the market does." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "4.1401496510016988" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# We'll generate a random factor\n", "current_factor_values = np.random.normal(0, 1, 10000)\n", "equity_names = ['Equity ' + str(x) for x in range(10000)]\n", "# Put it into a dataframe\n", "factor_data = pd.Series(current_factor_values, index = equity_names)\n", "factor_data = pd.DataFrame(factor_data, columns=['Factor Value'])\n", "\n", "# Now let's say our future returns are dependent on our factor values\n", "future_returns = -10 + current_factor_values + np.random.normal(0, 1, 10000)\n", "\n", "returns_data = pd.Series(future_returns, index=equity_names)\n", "returns_data = pd.DataFrame(returns_data, columns=['Returns'])\n", "# Put both the factor values and returns into one dataframe\n", "data = returns_data.join(factor_data)\n", "\n", "# Rank the equities\n", "ranked_data = data.sort('Factor Value')\n", "\n", "# Compute the returns of each basket\n", "# Baskets of size 500, so we create an empty array of shape (10000/500\n", "number_of_baskets = 10000/500\n", "basket_returns = np.zeros(number_of_baskets)\n", "\n", "for i in range(number_of_baskets):\n", " start = i * 500\n", " end = i * 500 + 500 \n", " basket_returns[i] = ranked_data[start:end]['Returns'].mean()\n", "\n", "basket_returns[number_of_baskets-1] - basket_returns[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Choice and Evaluation of a Ranking Scheme\n", "\n", "The ranking scheme is where a long-short equity strategy gets its edge, and is the most crucial component. Choosing a good ranking scheme is the entire trick, and there is no easy answer. A good starting point is to pick existing known techniques, and see if you can modify them slightly to get increased returns. More information on ranking scheme construction can be found in the notebooks listed below.\n", "\n", "During research of your ranking scheme, it's important to determine whether or not your ranking scheme is actually predictive of future returns. This can be accomplished with spearman rank correlation\n", "\n", "Information on construction and evaluation of ranking schemes is available in the following lectures:\n", "* [Universe Selection](https://www.quantopian.com/lectures/universe-selection)\n", "* [Spearman Rank Correlation](https://www.quantopian.com/lectures/spearman-rank-correlation)\n", "* [Factor Analysis](https://www.quantopian.com/lectures/factor-analysis)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Long-Short is a Modular Strategy\n", "\n", "To execute a long-short equity, you effectively only have to determine the ranking scheme. Everything after that is mechanical. Once you have one long-short equity strategy, you can swap in different ranking schemes and leave everything else in place. It's a very convenient way to quickly iterate over ideas you have without having to worry about tweaking code every time.\n", "\n", "The ranking schemes can come from pretty much any model as well. It doesn't have to be a value based factor model, it could be a machine learning technique that predicted returns one-month ahead and ranked based on that.\n", "\n", "We will be releasing sample long-short algorithms to go along with this notebook. Please stay tuned for those." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Additional Considerations\n", "\n", "###Rebalancing Frequency\n", "\n", "Every ranking system will be predictive of returns over a slightly different timeframe. A price-based mean reversion may be predictive over a few days, while a value-based factor model may be predictive over many months. It is important to determine the timeframe over which your model should be predictive, and statistically verify that before executing your strategy. You do want to overfit by trying to optimize the relabancing frequency, you will inevitably find one that is randomly better than others, but not necessary because of anything in your model.\n", "\n", "Once you have determined the timeframe on which your ranking scheme is predictive, try to rebalance at about that frequency so you're taking full advantage of your models.\n", "\n", "\n", "###Capital Capacity\n", "\n", "Every strategy has a minimum and maximum amount of capital it can trade before it stops being profitable. We will be releasing a full notebook discussing these concepts, but in the meantime consider the following.\n", "\n", "###Number of Equities Traded\n", "\n", "####Transaction Costs\n", "\n", "Trading many equities will result in high transaction costs. Say that you want to purchase $1000$ equities, you will incur thousands of dollars of costs per rebalance. Your capital base must be high enough that the transaction costs are a small percentage of the returns being generated by your strategy. Say that you are running $100,000$ dollars and making $1\\%$ per month, then the $1000$ dollars of transaction fees per month would take up your all of returns. You would need to be running the strategy on millions of dollars for it to be profitable over $1000$ equities.\n", "\n", "The minimum capacity is quite high as such, and dependent largely on the number of equities traded. However, the maximum capacity is also incredibly high, with long-short equity strategies capable of trading hundreds of millions of dollars without losing their edge. This is true because the strategy rebalances relatively infrequently, and the total dollar volume is divided by the number of equities traded. So if you turn over your entire portfolio of $100,000,000$ every month while running 1000 equities, you are only running $100,000$ dollar-volume per month through each equity, which isn't enough to be a significant market share for most securities." ] }, { "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 }