{ "cells": [ { "cell_type": "raw", "metadata": {}, "source": [ "---\n", "title: Calculate pair stats\n", "summary: Calculate mean, standard deviation and cdf of the ratio for the pair\n", "tags: [\"jugaad-data\", \"strategies\"]\n", "categories: [\"posts\"]\n", "date: 2020-08-25T02:02:57Z\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Before we proceed, I just want to comment about couple of decisions we made and make you aware that there are multiple options available.\n", "\n", "1. Choosing a pair\n", "For the current discussion we will select `JINDALSTEL` and `JSWSTEEL` because I found some trading opportunities in the time period we selected. (It is possible that you might not get an opportunity for a long time period and waiting for that opportunity is the most important part of the strategy. To mitigate that, you can track multiple pairs). This process can be repeated for each and every pair, but to keep things simple we will focus on just one pair.\n", "\n", "2. Choosing the variable for pair\n", "[The varsity article](https://zerodha.com/varsity/chapter/tracking-pairs/) describes three variables to describe the pair - Spread, Differential and Ratio. The [article later recommends](https://zerodha.com/varsity/chapter/the-density-curve/) using ratio as main variable for the pair.\n", "\n", "In this article, we will\n", "\n", "1. Download historical stock data for the pair\n", "2. Calculate the ratio of the pair\n", "3. Calculate the stats for the ratio - mean, standard deviation\n", "4. Plot 1σ, 2σ and 3σ values\n", "\n", "### 1. Download historical stock data for the pair" ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [], "source": [ "from datetime import date\n", "from jugaad_data import nse\n", "import pandas as pd\n", "import numpy as np\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [], "source": [ "\n", "from_date = date(2019,1,1)\n", "to_date = date(2019,6,30)\n", "sym_1 = \"JINDALSTEL\"\n", "sym_2 = \"JSWSTEEL\"\n", "stock_1 = nse.stock_df(sym_1, from_date, to_date)\n", "stock_2 = nse.stock_df(sym_2, from_date, to_date)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2. Calculate ratio of the pair" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [], "source": [ "ratio = stock_1['CLOSE'] / stock_2['CLOSE']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3. Calculate ratio stats" ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Mean (μ): 0.561 and Standard Deviation (σ): 0.0433\n" ] } ], "source": [ "mean = ratio.mean()\n", "stdev = ratio.std()\n", "print(\"Mean (μ): {:.3f} and Standard Deviation (σ): {:.4f}\".format(mean, stdev))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4. Plot" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will plot the ratio values against the mean and standard deviation lines to see how the ratio changed over the time period." ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [], "source": [ "fig,ax = plt.subplots()\n", "# Plot the ratio\n", "data_line = ax.plot(ratio, label='Ratio')\n", "\n", "# For drawing mean line\n", "mean_arr = [mean for _ in ratio]\n", "\n", "stdev_2_pos_line = ax.plot(mean_arr + 2 * stdev, label='μ + 2σ', linestyle='--')\n", "stdev_1_pos_line = ax.plot(mean_arr + stdev, label='μ + 1σ', linestyle='--')\n", "mean_line = ax.plot(mean_arr, label='μ', linestyle='--')\n", "stdev_1_neg_line = ax.plot(mean_arr - stdev, label='μ - 1σ', linestyle='--')\n", "stdev_2_neg_line = ax.plot(mean_arr - 2 * stdev, label='μ - 2σ', linestyle='--')\n", "\n", "# Make a legend\n", "legend = ax.legend(loc='upper right')\n", "\n", "fig.suptitle('Daily ratio', fontsize=20)\n", "plt.savefig('dailyratio.png')\n", "plt.close(fig)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![Daily Ratio](../dailyratio.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us see different levels around the mean-" ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " \t Ratio\n", "μ+3σ \t 0.691\n", "μ+2σ \t 0.648\n", "μ+1σ \t 0.605\n", "μ+0σ \t 0.561\n", "μ-1σ \t 0.518\n", "μ-2σ \t 0.475\n", "μ-3σ \t 0.432\n" ] } ], "source": [ "print(\" \\t Ratio\")\n", "for i in range(3, -4, -1):\n", " r = mean + i * stdev\n", " print(\"μ{0:+}σ \\t {1:.3f}\".format(i, r))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Decision matrix\n", "\n", "I have modified the entry and exit logic slightly from what is described in the varsity article-\n", "\n", "| Position | Entry condition | Entry Ratio | Exit condition | Exit Ratio | Stop Loss | Stop loss ratio |\n", "|----------|-----------------|-------------|----------------|------------|-----------|-----------------|\n", "| **Long** | < μ - 2σ | < 0.475 | > μ - 1σ | > 0.518 | < μ - 3σ | < 0.432 |\n", "| **Short**| > μ + 2σ | > 0.648 | < μ + 1σ | < 0.605 | > μ + 3σ | > 0.691 |\n", "\n", "You can see that ratio barely touched (μ - 2σ) and (μ + 2σ) level once each. So these opportunities are not very common.\n", "\n", "We ran our analysis on Jan 2019 to Jun 2019 data, we will backtest this strategy on next six months ie. from July 2019 to Dec 2019.\n", "\n", "At the time of the writing, I'm not sure if we will find any opportunity, will we make profit or we will hit a stoploss, lets find out in the next section.\n", "\n", "### [Next step](../pair-trade-test/)\n", "\n", "### [Go back to index](../)\n", "\n", "### [Download notebook](../pair-stats.ipynb)\n" ] } ], "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 }