{ "cells": [ { "cell_type": "raw", "metadata": {}, "source": [ "---\n", "title: \"How to calculate beta for Indian stocks using python and jugaad-data\"\n", "date: 2020-08-23T08:47:11+01:00\n", "images: ['beta.svg']\n", "draft: false\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![beta](beta.svg)\n", "\n", "## What is Beta in finance\n", "\n", "Beta is measure of risk/volatility of a stock. The fundamental assumption is that returns of a stock are linearly co-related to returns of an index, which means they can be defined by a linear equation like `y = mx + c`. \n", "\n", "Mathematically β can be defined as slope of line defining relation between stock and index ie-\n", "\n", "`return_stock = β x return_index + α + e`\n", "\n", "β can be calculated by [regression with below formula](https://en.wikipedia.org/wiki/Beta_(finance)#Mathematical_Definition)\n", "\n", "`β = Cov(return_stock, return_index)/Var(return_market)`\n", "\n", "You can read more about it [here](https://en.wikipedia.org/wiki/Beta_(finance))-\n", "\n", "There are readymade filters online based on beta like [topstockreasearch.com](https://www.topstockresearch.com/TopMenu/ScreenerByTechnicalIndicatorforIndianMarket.html#Beta), but if you want to know how to calculate it by yourself, read on-\n", "\n", "## How to interprete it\n", "\n", "As mentioned earlier, it is measure of volatility. \n", "\n", "|Value of beta | Interpretation |\n", "|-------|--------|\n", "| > 1 | Stock is more volatile than the index but moves in same direction, ie. if stock has a beta of 1.2, when the NIFTY moves by +1%, the stock is likely to move by +1.2%, but similarly when index falls by -1% stock will likely fall by -1.2% |\n", "| < 1 | Stock is less volatile than the index and moves in same direction slower than index, ie. if stock has a beta of 0.5, when the NIFTY moves by +1% stock is likely to move by +0.5%, but similarly when index falls by -0.5% stock will likely fall by -0.5%\n", "| < 0 | Negative beta means stock moves in opposite direction of the index. if stock has a beta of -1.2, when the nifty moves by +1%, the stock will likely fall -1.2% and vice-verca|\n", "\n", "Hope this gives you a good idea. Please do read more about it on [investopedia](https://www.investopedia.com/investing/beta-know-risk/#:~:text=Beta%20is%20a%20measure%20of,relation%20to%20the%20overall%20market.&text=If%20a%20stock%20moves%20less,risk%20but%20also%20lower%20returns.)\n", "Beta is also used in [Modern Portfolio Theory](https://en.wikipedia.org/wiki/Modern_portfolio_theory) and for [calculating Equity risk premium in CAPM](https://en.wikipedia.org/wiki/Modern_portfolio_theory)\n", "\n", "Now that we have understood the finance concepts, let us now look at the code\n", "\n", "## Download required historical data\n", "\n", "Hope you have installed `jugaad-data` and `pandas` using pip. If not, just run `pip install jugaad-data pandas` to install it.\n", "\n", "We will download last six months data. " ] }, { "cell_type": "code", "execution_count": 101, "metadata": {}, "outputs": [], "source": [ "from datetime import date\n", "import pandas as pd\n", "from jugaad_data.nse import index_df, stock_df" ] }, { "cell_type": "code", "execution_count": 102, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Index Name INDEX_NAME HistoricalDate OPEN HIGH LOW CLOSE\n", "0 Nifty 50 NIFTY 50 2020-06-01 9726.85 9931.60 9706.95 9826.15\n", "1 Nifty 50 NIFTY 50 2020-05-29 9422.20 9598.85 9376.90 9580.30\n", "2 Nifty 50 NIFTY 50 2020-05-28 9364.95 9511.25 9336.50 9490.10\n", "3 Nifty 50 NIFTY 50 2020-05-27 9082.20 9334.00 9004.25 9314.95\n", "4 Nifty 50 NIFTY 50 2020-05-26 9099.75 9161.65 8996.65 9029.05\n", " DATE SERIES OPEN HIGH LOW ... 52W L VOLUME VALUE NO OF TRADES SYMBOL\n", "0 2020-06-01 EQ 1480.00 1538.35 1475.95 ... 875.65 18434065 2.789048e+10 354436 RELIANCE\n", "1 2020-05-29 EQ 1468.00 1472.00 1452.65 ... 875.65 18471770 2.702029e+10 300018 RELIANCE\n", "2 2020-05-28 EQ 1455.00 1479.75 1449.00 ... 875.65 18519252 2.717698e+10 405603 RELIANCE\n", "3 2020-05-27 EQ 1431.00 1454.00 1412.00 ... 875.65 16460764 2.354223e+10 348477 RELIANCE\n", "4 2020-05-26 EQ 1448.15 1449.70 1416.30 ... 875.65 15330793 2.190317e+10 341795 RELIANCE\n", "\n", "[5 rows x 15 columns]\n" ] } ], "source": [ "idx = index_df(\"NIFTY 50\", date(2020,1,1), date(2020,6,1) )\n", "stk = stock_df(\"RELIANCE\", date(2020,1,1), date(2020,6,1))\n", "print(idx.head())\n", "print(stk.head())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can read more on `jugaad-data` capabilities in the [documentation](https://marketsetup.in/documentation/jugaad-data/)\n", "\n", "## Transformation and clean up\n", "\n", "Basic clean-up\n", "* In NIFTY's dataframe replace column name 'HistoricalDate' with 'DATE' so that we can merge the two data frames\n", "* Create new merged dataframe with new column names ie. NIFTY and STK\n" ] }, { "cell_type": "code", "execution_count": 103, "metadata": {}, "outputs": [], "source": [ "idx['DATE'] = idx['HistoricalDate']" ] }, { "cell_type": "code", "execution_count": 104, "metadata": {}, "outputs": [], "source": [ "df = idx[[\"DATE\", 'CLOSE']]\n", "df.columns = ['DATE', \"NIFTY\"]" ] }, { "cell_type": "code", "execution_count": 105, "metadata": {}, "outputs": [], "source": [ "df = pd.merge(df, stk[['DATE', 'CLOSE']], how='inner', on='DATE')\n", "df.columns = ['DATE', 'NIFTY', 'STK']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Calculate returns for both stock and nifty\n", "\n", "Now you can calculate beta on daily, weekly or monthly returns depending on your use case, we are going to calculate beta on daily returns here, you can shift by 5 if you want a weekly return." ] }, { "cell_type": "code", "execution_count": 112, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " DATE NIFTY STK STK_PREV NIFTY_PREV NIFTY_CHG STK_CHG\n", "2 2020-05-28 9490.10 1472.25 1464.40 9580.30 -0.009415 0.005361\n", "3 2020-05-27 9314.95 1445.55 1472.25 9490.10 -0.018456 -0.018136\n", "4 2020-05-26 9029.05 1424.05 1445.55 9314.95 -0.030693 -0.014873\n", "5 2020-05-22 9039.25 1431.55 1424.05 9029.05 0.001130 0.005267\n", "6 2020-05-21 9106.25 1441.25 1431.55 9039.25 0.007412 0.006776\n" ] } ], "source": [ "df['STK_PREV'] = df['STK'].shift(1)\n", "df['NIFTY_PREV'] = df['NIFTY'].shift(1)\n", "df['NIFTY_CHG'] = (df['NIFTY']-df['NIFTY_PREV'])/df['NIFTY_PREV']\n", "df['STK_CHG'] = (df['STK']-df['STK_PREV'])/df['STK_PREV']\n", "df.dropna(inplace=True)\n", "print(df.head())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Calculate Covariance, Variance and ultimately the Beta\n", "\n", "Numpy provides you readymade functions to calculate Covariance and Variance of a series.\n", "\n", "A note on np.cov function, it returns a covariance matrix, eg\n", "np.cov(a,b) returns-\n", "\n", "```\n", "[\n", " [cov(a,a), cov(a,b)],\n", " [cov(b,a), cov(b,b)]\n", "] \n", "```\n", "So either select [1,0] or [0,1]\n", " \n" ] }, { "cell_type": "code", "execution_count": 107, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "cov = np.cov(df['STK_CHG'], df['NIFTY_CHG'])\n", "var = np.var(df['NIFTY_CHG'])" ] }, { "cell_type": "code", "execution_count": 110, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[0.00156533 0.00096934]\n", " [0.00096934 0.0008748 ]]\n" ] } ], "source": [ "print(cov)" ] }, { "cell_type": "code", "execution_count": 111, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.119145517341673\n" ] } ], "source": [ "print(cov[1,0]/var)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Conclusion\n", "\n", "In this article we learnt\n", "- What is beta and how to interprete it\n", "- How to download data from NSE using `jugaad-data`\n", "- How to calculate beta using pandas and numpy\n", "\n", "You can download the ipython notebook [here](beta.ipynb)\n", "\n", "Hope you learnt something interesting\n", "\n", "![https://media.giphy.com/media/tuvMgAPzxaQBq/giphy.gif](https://media.giphy.com/media/tuvMgAPzxaQBq/giphy.gif)" ] } ], "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.8.3" } }, "nbformat": 4, "nbformat_minor": 4 }