0% found this document useful (0 votes)
408 views93 pages

Trading Pairs With Excel Python by Anjana Gupta @tradingpdfgratis2

Uploaded by

robaten153
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
408 views93 pages

Trading Pairs With Excel Python by Anjana Gupta @tradingpdfgratis2

Uploaded by

robaten153
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 93

Trading Pairs

Advance Statistical Tools for Trading in Python

Anjana Gupta
Contents

Title Page
Disclaimer
Preface
Pair Trading: Introduction
Basics of Python
Fetching historical data
Basics of Statistics
MEAN
HISTOGRAM
PROBABILITY
Standard Deviation & Variance
Bollinger Band
Correlation
LINEAR REGRESSION
Stationary Time Series
Z-Score
Pair trade backtesting setup in Google Spreadsheet
Pair trade backtesting in Python
Machine Learning for Pair Trading
Python Codes @ GITHUB
About Authors / Acknowledgments
Books By This Author
Books By This Author
Books By This Author
Disclaimer

This book is educational in nature. Various Derivative contracts


traded in Indian market and data used in various examples are for
illustrative and educational purpose only. Example/ data used may
or may not be based on Historical/factual data. We are not
rendering legal/professional services or any kind of advice for
trading. Past performance or data or example discussed here does
not guarantee of future results. We disclaim any liability/loss/risk
resulting directly or indirectly from use or application of any
content of this book.
Preface

This is a comprehensive guide on pair trading. Concepts are explained from


very basic so that any trader who does not understand statistics can
understand and learn. Models are developed in Google spread sheet and
Python for back testing and finding opportunities. Python is also explained
from very basic so that anyone who does not understand python or
programming can write and develop his own codes for fetching historical
data and back testing. Machine learning tools in Python are also used for
back testing and finding opportunities.

When you start independent trading than fear of loss is natural. One
should not have a immediate need of profit to sustain his daily living. If yes
then trading with your own money in not for you. Better you go for a salary
based proprietary trader with any broker. Trading with own money is for
those who have surplus funds and some other source of earning for daily
living. In India hundreds of professional traders are earning bread and butter
from trading, but mostly are doing arbitrage from co-location and they also
have some fixed income from arbitrage, arbitrage again is not risk free but
these professional traders have provisions for losses. Till 2008 when algo
trading was not there in India hundreds of manual jobbers earning bread and
butter from manual arbitrage. When algo trading came, manual jobbers who
have not updated themselves became dealer, joined in back office or
operation department and many gone out from the market. Who upgraded
themselves with latest knowledge of algos are still in the game. You must
have heard about diversification. Apply this rule in your income also.
Diversify your sources of income. So my suggestion for professional traders
also that should develop some secondary source of income apart from full
time trading may be like buying a commercial property and earning fixed
rental income. Diversify your trading strategies also. Work on many
strategies so that you can remain profitable even if some strategies gives you
loss. Nothing is permanent if you are in capital market so you need to keep
yourself updated with knowledge and new skills. When excel came you
learned first time and today its part of daily life, in the same way you could
make yourself familiar with Python also. When you will keep using it
regularly you will be able to do many things which are not possible in Excel.
In Python you can analyze thousands of data point in few seconds. Today
Statistical trading is not easy without software like Python. If you want to go
to next level of trading than knowledge of any software like python is
essential.

In this book we have developed models on excel as well as Python. In


this book first we will learn some basics of statistics useful in trading, we
will develop a model on excel after that we will learn machine learning for
pair trading.

If you do not know Python or programming then I will suggest you read
my first book ‘Option Greeks, Strategies & Backtesting in Python’ available
on Amazon. First book covers derivative, Option Greeks, Option strategies,
basic of python, how to fetch past data in Python, back testing of option
strategies on past data. First book covers options trading in details and also
explain why trading options are better than trading naked future position.
This is second book of the series. This book is written for individuals and
traders. With help of this book individual trader, investor can understand
statistical tools of pair trading and machine learning for pair trading.
Pair Trading: Introduction
A pair trading is a market neutral trading strategy (meaning market
direction doesn’t matter) that involves matching a long position with a short
position in two stocks with a high correlation. Pair trading is a statistical
arbitrage strategy, which is based on the mean reversion principle. While it
isn’t riskless, by understanding how pairs trading works, how you control
risk and how you manage profits, it’s a great tool to add to your trading
arsenal !
A pair trading strategy is based on the historical correlation of two
securities. Do not rely 100% on statistics and mathematics in trading. If you
will find correlation in top 500 stocks trading on exchange then you may
find correlation in many stocks which are not from same sector or having
same market capitalization. It’s not a good idea to trade stocks from 2
different sector or different market capitalization. Look for stocks from the
same sector, having similar business model and comparable market cap
as they have the highest chance to be co-integrated over a longer time
horizon. Same sector and comparable size immunes the pair from
unexpected news flow regarding the sector as a whole. Be it negative news
or positive, both stocks will hopefully move in the same direction - and this
is what is desired in pair trade.
The securities in a pair trade must have a positive correlation, which is
the primary driver behind the strategy’s profits. A pair trade strategy is best
deployed when a trader identifies a correlation discrepancy. Relying on the
historical notion that the two securities will maintain a specified correlation,
the pairs trade can be deployed when this correlation falters.
To illustrate the potential profit of the pairs trade strategy, consider Stock
A and Stock B, which have a high correlation of 0.95. The two stocks
deviate from their historical trending correlation in the short-term, with a
correlation of 0.75. The arbitrage trader steps in to take a dollar/rupee
matched the long position on underperforming Stock A and a short position
on outperforming Stock B. The stocks converge and return to their 0.95
correlation over time. The trader profits from a long position and closed
short position.
So basic idea in pair trading is to trade the two stocks by studying its
historical relationship and spotting an opportunity which has arisen due to
breakdown in the correlation and essentially we are betting that the gap
would come back to its original state (called mean reversion). If you are
implementing a mean reversion strategy, you are assuming that the mean
will remain the same in the future as it has been in the past. But mean can
also change over a period of time. So trading pairs is not a risk-free strategy.
The difficulty comes when prices of the two securities begin to drift apart,
i.e. the spread begins to trend instead of reverting to the original mean.
Dealing with such adverse situations requires strict risk management rules,
which have the trader exit an unprofitable trade as soon as the original setup
—a bet for reversion to the mean—has been invalidated. So pair trading is a
market-neutral strategy to an extent only. Mean can change, hence, please
do not be under the impression that pair trading is a 100% market neutral
strategy. So you can say this is a trading strategy that seeks to take advantage
of price differentials between two, related assets.
Therefore, the bulk of the work in pair trading revolves around
identifying the relationship among the stocks of same sector, quantifying
their relationship, tracking the behavior of this relationship on a minutes/
hourly/ daily basis and looking for anomalies in the price behavior. When an
anomaly occurs an opportunity to trade arises. In pair trading, you buy the
undervalued security and sell the overvalued one that is why it is also called
statistical arbitrage.
All of the above things could be done by machine itself. We will also
learn machine learning for pair trading in this book. Let’s start with some
basics. First you need past data of stocks so that you can quantify
relationship among various stocks of same sector. You can fetch past data in
excel from Google spread sheet, you can also fetch past data in Python using
Jupyter notebook. I will explain both. I will suggest you to learn python if
you do not know because machine learning tools are not available in Excel.
Basics of Python
First you need to open Jupyter Notebook in Google colab in any browser.
Open Google > Search Google Colab > Open Google Colab > click on
file > open new notebook.

Click on new notebook than a new notebook will open, will look like this –

I have given print command in 1st cell. You can write and execute
commands in cell. Get familiar with the Jupyter Notebook interface. Now
Jupyter Notebook is your playground. Jupyter Notebook is an interactive
document. You need to write commands in predefined format and on
execution of commands you get results of your commands. It’s easy; you can
learn basics of python thru any video available on Google. Good thing with
python is that past data of exchanges and tools are already available. Most of
the professional traders use python or c++ for development and back-testing
of strategies. You need not to learn complete programming language. You
can analyze data in the way you want for that you need to learn basics of
programming. In coming chapters we will learn how to write program and
how Python will help in past data analysis for any strategy. With
understanding and use of limited commands you can backtest your
strategies. So I used limited commands and functions for better
understanding. Let’s start with some basic of Python.

First you need to understand that you need to give commands in predefined
format, it is called coding. Programming languages understand commands in
predefined format. Initially you will make lots of mistake in coding and
gradually you will learn how to write program code.

Open a new Jupyter note book. Type following in a cell (code written in blue
color is python code. Statement written after ‘#’ is explanation in English,
it’s not a part of code, it is just to explain you the code) –

a=100 # here you assigned value of 100 to a variable ‘a’


b=a/2 # here you assigned value of 50 (‘a’ divide by 2) to variable ‘b’
c=a+b # here you assigned value of 150 (value of a + value of b) to variable
‘c’
d=(a*3)-b # here you assigned value of 250 [(a X 3)-b] to variable ‘d’
print (a,b,c,d) # here you are giving print command to print values of ‘a’, ’b’,
’c’ and ‘d’

Than you can click on ‘run’ button. You will get the results of your
command. Jupyter notebook will print the value of ‘a’, ‘b’, ‘c’ and ‘d’ as per
your command. Python makes use of simple syntax which looks like written
English.

Be creative, do various experiment with codes in notebook. This will help


you to learn more about programming.
Second you need to understand modules in python. If you want to use
mathematical functions in Jupyter sheet than you need to import math
module.

For option trader one of the basic module required is NumPy. It is used for
Scientific Computing. If you will observe the next screen shot, I have
imported module numpy and I have given command to find minimum value
out of 3, 6, and 9. We are using Np.min() command from numpy module.
You will check out of command is 3. So program itself found the minimum
value out of 3 values.

In next cell I have given command to find maximum value. Result of this
command is 9. So program itself found the maximum value out of 3 values

So we are giving commands in predefined format and software is giving


output of that command.

Math, NumPy are the Built-in modules, these modules are available by
default in Python. But there are many other publicly available module which
you may want to use. To install a module following command is used in
python –
!pip install <module name>

Third and the most important thing a trader need is past data. Various options
are available to get past data. You can download data from yahoo finance.
The nsepy module module is used to get the stock market data for contracts
traded on both exchanges. You can install these modules thru following
commands –
!pip install yfinance
Forth you need to understand data in tabular format in python. Tabular
format comprising of row and columns like Excel spread sheet in python this
is called ‘dataframe’. You can perform anything in a particular row and
column thru commands in python. Trader can fetch past data thru yfinance in
tabular format, we will learn this in next chapter. You can also import and
export csv/excel files in python. You can perform various functions on a
table in python like you do on ‘Excel’. Some basic functions required for
past data analysis and strategy backtesting are discussed below -

Following command will be used for import of data of a file saved on your
laptop –

Table = pd.read_csv('filename.csv')

Following command will be used to save data in a file on your laptop (export
data) –

filename.to_csv("giveanyname.csv", index=True, encoding='utf8')

Following codes are required to download file from Google Colab -

filename.to_csv("filename.csv", index=True, encoding='utf8')


from google.colab import files
file.download('filename.csv')

Codes to create table (DataFrame) in Python itself by typing values-

import pandas as pd
data = {'Stocks': ['Reliance', 'Infosys', 'TCS'],
'Price': [1200, 700, 2500]}

Table = pd.DataFrame(data, columns = ['Stocks', 'Price'])

print (Table)

Add new column in Table with following command –


Table['Quantity'] =0

Check columns with following command –


Table.columns

Select last 2 values of column ‘Price’ in new variable ‘last’ with following
command –
last = Table['Price'][-2:]

Select maximum and minimum value in a table from following commands –


Table.column.max()
Table.column.min()

You can insert value in any cell thru following command –


Table.loc[0, 'Quantity'] = 10
#this command will insert value ‘10’ in 1st row of column ‘Quantity’
You can also perform various mathematical/statistical functions between
columns –

Table['Amount']=Table['Price']*Table['Quantity']
Following command can be used for cumulative sum of any column –

Table['Total'] = Table['Amount'].cumsum()

Following command could be used to delete columns –

Table.drop(["Total", "Amount"], axis = 1, inplace = True)


Now let’s learn some other functions of Python that we are going to use in
coming chapters –

Object Oriented Programming - You can create your own function in


Python. In the following example you have created a new function
‘my_function’ which multiply ‘Price’ and ‘Quantity’ of any table. So you
can perform a single command or set of commands in your function and you
need not to write these codes again and again. That is why it is called object
oriented programming.

def my_function(df):
try:
return (df['Price']*df['Quantity'])
except:
return np.NaN

Table['Amount'] = Table.apply(my_function, axis=1)


print (Table)

Range - To loop through a set of code a specified number of times we can


can use a ‘range’ function. Let me explain how these loops works. Jupyter
note book will print the value of ‘x’ 4 times if you will write following code
-

x=1
for x in range (1, 5):
print (x)
The range() function defaults to increment the sequence by 1, however it is
possible to specify the increment value by adding a third parameter:

for x in range (1, 15, 2):


print (x)

Lambda - you can create your own function through lambda. Here x and y
are the parameters and x+y is the operation performed. So when you will use
xyz in your code you will get addition of 2 values as result.

xyz = lambda x,y: x+y


xyz (3,6)

Now you have basic understanding of python. Some codes to compute profit
and loss of few strategies on past data given in coming chapters. Same codes
could be used for computation of profit and loss of strategy for any contract
and for any period. You just need to download code files from link given at
end of this book.

Free Resources

This book is written for pair trading not for python. Still I explained
some basics of python required for a trader. If you do not understand python
then I will suggest you to learn some basics of python first. You can also
enroll for free basic course on Python through following link -

https://quantra.quantinsti.com/course/python-trading-basic
Fetching historical data
Past Data on Google Spreadsheet

Google Sheets is a spreadsheet program included as part of the free,


web-based Google Docs office suite offered by Google within its Google
Drive service. Google Sheet fetches current or historical securities
information from Google Finance. You can open Google spreadsheet in any
browser. Use following syntax to fetch data -
GOOGLEFINANCE(ticker, [attribute], [start_date],
[end_date|num_days], [interval])
One of the following attribute can be used for real-time data as well as
historical data :
"price" - Real-time price quote, delayed by up to 20 minutes.
"priceopen" - The price as of market open.
"open" - The opening price for the specified date(s).
"close" - The closing price for the specified date(s).
"high" - The high price for the specified date(s).
"low" - The low price for the specified date(s).
"volume" - The volume for the specified date(s).
"closeyest" - The previous day's closing price.

A sample screen shot of fetching historical data in Google spreadsheet is


given below-
Past data on Google Colab (Python Jupyter note book)-

Colab is a Python development environment that runs in the browser


using Google Cloud. One can use Google colab to run python codes or you
may download anaconda on your laptop and you can use Jupyter notebook to
run codes. One can open Google colab in any browser.
Open Google > Search Google Colab > Open Google Colab > click on
file > open new notebook.

Following codes could be used to fetch past data. First you need to install
required libraries. Past data could be fetched from yfinance or NSEPY could
be used to fetch data of NSE India. In the following example I am fetching
historical prices of 'HDFC' trading on NSE India from yahoo finance.
!pip install yfinance
from datetime import datetime
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import yfinance as yf
data = yf.download('HDFC.NS', start="2020-01-01", end="2019-01-31")

A sample screen shot of fetching historical data in Google Colab is given


below-
When you will run the code data of given period will store in variable
‘data’. You can check with print command. Click on Code button given on
upper left side of notebook and type the following command. You will get
following output when you will run the code (Click on run button).
Installation of Python Jupyter Notebook on Laptop
First get python installed on your system/laptop. You can download
anaconda installer from following link-

https://www.anaconda.com/products/individual

Run the installer, installation of anaconda is like installation of any other


program on your system. After installation Go to all program menu of your
system/laptop, when you will search all programs you will find one folder
with the name of Anaconda. Click on Anaconda, there will be many options,
click on Jupyter Notebook. Jupyter notebook will look like this –
Click on new > Python 3 than a new notebook will open, will look line
this –

I have given print command in 1st cell. You can write and execute
commands in second highlighted green cell.
Per Minutes historical data through yfinance

You can also download 1 minute historical data of last 10 days from
yfinance. Following codes will be used to get 1 minute data –

minu_data = yf.download('HDFC.NS', start="2021-01-01", end="2021-01-


02", interval="1m")

Following is the screen shot –

Intraday chart can also be plotted to check price movement –


Live Data through yfinance

You need to install package yahoo_fin to get Live stock quotes using web
scraping tools. The following code gets the real-time stock price during
market hours.

!pip install requests_html


!pip install yahoo_fin
from yahoo_fin import stock_info
from datetime import time
now = datetime.now()
price = stock_info.get_live_price("HDFC.NS")
print(now, 'HDFC Price:', price)

Following is the screen shot –


Historical Data through QUANDL

Quandl is a platform that provides its users with economic, financial and
alternative datasets. According to Quandl, their user amount is over 400,000
people, which ranges from the world’s top hedge funds to investment banks
and various asset managers. Quandl want to inspire customers to make new
discoveries and incorporate them into trading strategies. They believe there
are new and better ways to understand the complex information that creates
markets and market movement. They believe that data, and alternative data
in particular, is going to become the primary driver of active investment
performance over the next decade.
Quandl offers both free and premium products. The Quandl API is free to
use and grants access to all free datasets. Quandl users only pay to access
Quandl’s premium data products. In this book we will use free data available
on quandl.

Quandl is really easy to use and is beginner-friendly. All you need to do is to


go to their website (https://www.quandl.com/) and register for an account.
After that you’ll get your API key that allows you to fetch data from quandl.

The best thing with Quandl is that data is free, transparent, easy to find and
cleaned.

First you need to create account with Quandl and you will get API Key.
After that you need to install Quandl library with following command –

!pip install quandl

Following codes can help you to fetch historical data. In the following
example I am fetching WTI Crude oil prices of CME –

import quandl
start = datetime(2020, 1, 1)
end = datetime(2020, 12, 31)
df = quandl.get('CHRIS/CME_CL1', start_date=start, end_date=end, qopts=
{'columns': ['Settle']}, authtoken='insert you key that you get on registration
with quandl')
plt.figure(figsize=(20,10))
plt.plot(df.Settle)

You will get the following output –

Further you can learn from Quandl website itself about how to fetch data in
python –

https://www.quandl.com/tools/python
Basics of Statistics
MEAN
Mean is average of all numbers. Mean value is sum of all numbers
divided by count of all numbers.
For example a stock has given a return of 5%, 8%, 15%, 2% and 10% in
last 5 years. What is average return?
Average return = (5+8+15+2+10) / 5 = 8
So mean value is 8, you can say stock has given a average return of 8%
in last 5 years.
Let’s compute mean value in Google Sheet and Google Colab. In the
following example we are computing moving average of data of HDFC we
fetched in Google sheet and Google Colab. We are computing 20 days
moving average of close price of S.No. 1 to 20 in cell D28 as shown in
following screenshot. Again 20 days moving average of close price of S.No.
2 to 21 in cell D29 and so on. Moving average is series of average of
different subsets of the full data set. The average is taken over for a specific
period of time for example 30minuts, 30 days, 50 days etc.

Following commands can be used to compute moving average (rolling


average) in a Jupyter note book. We have taken a window of 20 days.
data[‘Moving_average’] = data[‘Close’].rolling(window=20,
min_periods=1,center=False).mean()
You can check the output of above using following command.
data.tail(20)
You will get the following output of above commands. We have moving
average of last 20 trading days in last column.

You can plot the chart of Close price and moving average we have
computed with the following command -
data[['Close', 'Moving_average']].plot()
You will get following output.

In the above chart blue line is close price and orange line is last 20 days
moving average. Moving average crossover is used to generate buy or sell
signals. If short period moving average line is above the long period moving
average then it’s a buy signal and if short period line is below the long
period line it is sell signal. This works in trending market but in rage bound
market this strategy may give losses. In range bound market mean reversal
strategy will give you profit.

Trading on Moving average crossover -

Some investors trades on moving average cross over. Which moving


average use for trading is a very subjective decision and it may depend on
contract you are trading. Let’s backtest the returns given by moving average
crossovers on past data.

In the following example we have computed return given by Reliance


Industries during the period from 1st January 2020 to 30th October 2020 on
10 days and 30 days moving average crossover. In the given Trader is
buying Reliance when 10 days moving average is crossing 30 days moving
average from downside and trader is selling when 10 days moving average is
30 days moving average from upside.
Python code -

!pip install yfinance


from datetime import datetime
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import yfinance as yf

Stock = "RELIANCE.NS"
data = yf.download(Stock, start="2020-01-01", end="2020-10-31")

T = pd.DataFrame({"Close": data["Close"]})
SMA=10
LMA=30

# Compute Moving averages of last 10 days and 30 days closing prices


T['Short_average'] = T['Close'].rolling(window=SMA, min_periods=1,
center=False).mean()
T['Long_average'] = T['Close'].rolling(window=LMA, min_periods=1,
center=False).mean()
T['positions_long'] = np.nan

for x in range (len(T)):


if T.Short_average[x] > T.Long_average[x]:
T['positions_long'][x] = 1
if T.Short_average[x] <= T.Long_average[x]:
T['positions_long'][x] = 0

T.positions_long = T.positions_long.fillna(method='ffill')

T['price_difference']= T.Close - T.Close.shift(1)


T['pnllong'] = T.positions_long.shift(1) * T.price_difference
T['cumpnl_long'] = T.pnllong.cumsum()

print(T)

You will get the follwoing output -

If you will observe the above output you will find that Reliance was
trading at Rs 1509/- on 1st January 2020 and at Rs 2054/- on 30th October
2020. If any investor bought on 1st January 2020 then sold at 30th October
2020 then trader earned Rs 545/-. However if trader is trading on 10 days
and 30 days moving average crossover then trader earned Rs 747/-.
Which moving averages to take for trading is a very subjective decision.
However with the help of Python we can backtest return given by stock on
various moving averages in various periods. Backtesting of this on Google
spreadsheet or Excel is going to be a very time consuming activity. Lets do it
with the help of Python codes. I have written following codes in which one
can define stock, years, short moving averages and long moving averages to
get returns. With the help of following code I am computing yearly return
given by Reliance Industries during the year 2016 to 2020 on different
combinations of moving average crossovers from 1 to 35. Trader is buying
when short moving average is crossing long moving average from downside
and selling when short moving average is crossing long moving average
from upside.

If you will observe the following code you will notice that I have used 3
‘for’ loops. 1st ‘for’ loop for years, 2nd ‘for’ loop for short moving average
and 3rd for loop for long moving average. Pivot Table created with values of
‘cumpnl_long’. This field of ‘cumpnl_long’ is giving us the per share return
given by stock when we are having long position if short moving average is
above long moving average

Python Code -

!pip install yfinance


from datetime import datetime
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import yfinance as yf

# Fetch historical data


Stock = "RELIANCE.NS"
data = yf.download(Stock, start="2016-01-01", end="2020-10-31")

T3 = pd.DataFrame({"Close": data["Close"]})
T3['Year'] = T3.index.year
T2 = pd.DataFrame({"cumpnl_long":['0'], "SMA":['0'], "LMA":['0'],
"Year":['0']})

for z in range (2016, 2021, 1):


T = T3.where(T3.Year == z)
T = T.dropna()
for a in range(1,35,2):
for b in range(a,35,2):
SMA=a
LMA=b

# Compute Long and short Moving averages


T['Short_average'] = T['Close'].rolling(window=SMA,
min_periods=1, center=False).mean()
T['Long_average'] = T['Close'].rolling(window=LMA,
min_periods=1, center=False).mean()

T['positions_long'] = np.nan

for x in range (len(T)):


if T.Short_average[x] > T.Long_average[x]:
T['positions_long'][x] = 1
if T.Short_average[x] <= T.Long_average[x]:
T['positions_long'][x] = 0

T.positions_long = T.positions_long.fillna(method='ffill')
T['price_difference']= T.Close - T.Close.shift(1)
T['pnllong'] = T.positions_long.shift(1) * T.price_difference
T['cumpnl_long'] = T.pnllong.cumsum()
T1 = T[['cumpnl_long']].tail(1)
T1['SMA'] = SMA
T1['LMA'] = LMA
T1['Year'] = z
T2 = T2.append(T1)

#Create pivot table


Pivot_Table1 = pd.pivot_table(T2, values ='cumpnl_long', index =
['SMA', 'LMA'], columns =['Year'], aggfunc = np.sum)

#Export pivot table


Pivot_Table1.to_csv("PV_T.csv", index=True, encoding='utf8')
from google.colab import files
files.download('PV_T.csv')

You will get the following output in Excel downloaded-

In the above output of excel you will observe moving average crossover
of 1 day and 5 days is giving consistent return year on year (SMA denotes
short moving average and LMA denotes long moving average). So
technically you can say Reliance is buy if trading above 5 days moving
average. But this will result into many trades and cost is associated with
every trade. If you will observe moving average crossover of 1 day and 29
days is also giving consistent return. It means if Reliance is trading 30 days
moving average its a buy.
One more thing you will notice that in year 2020 all the moving averages
has given very good return because prices were trending in year 2020. We
have seen rollercoaster ride in year 2020 from Nifty 12000 to 8000 and
again back to 12000. In trending market moving average crossover gives
good return however in range bound market mean reversal strategies gives
good return.
As we have computed return for Reliance, in the same way you can
compute moving average return given by any stock on past data for any
combination of moving averages.
HISTOGRAM
Histogram is graphical display of data using bars. It’s similar to bar
chart, but in case of Histogram each bar shows how many values fall into
each range. Let’s take example. We have 9 months HDFC prices in table
data.

Lets compute how many times HDFC closed above previous close and
how many times it closed below previous close. We can use the following
command to plot the histogram –

data[‘return’] = data[‘Close’].pct_change()
plt.hist(data['return'], bins=[-1,0,1])
We will get the following output-

In year 2020 out of 207 trading days 106 days HDFC closed below last
day closing price and 101 days HDFC closed above the last trading day
closing price.
PROBABILITY
Probability is how likely something is to happen. Many events can't be
predicted with total certainty. The best we can say is how likely they are to
happen, using the idea of probability. So probability helps us to make
decision by quantifying the uncertainty.

Probability = Count of true events / Total number of Events


When a coin is tossed there are 2 possible outcomes either head or tail,
each one has 50% probability. When a single dice is thrown there are 6
possible outcomes so probability of any one of them is 1/6 (16.67%).
We have open and close price of 208 trading days of 2020. Let’s
compute what is the probability that HDFC will close above previous day
close price if any day open price is above the previous trading closing price
or HDFC will close below previous day close price if any day open price is
below the previous trading day closing price.
Following program codes can be used to compute –
# Download necessary libraries
!pip install yfinance
from datetime import datetime
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import yfinance as yf

# Computation of reruns
data = yf.download(‘HDFC.NS’, start="2016-01-01", end="2020-10-
31")

data['buysignal'] = np.where((data['Open'] > data['Close'].shift(+1)) &


(data['Close'] > data['Close'].shift(+1)), 1.0, 0.0)
data['sellsignal'] = np.where((data['Open'] < data['Close'].shift(+1)) &
(data['Close'] < data['Close'].shift(+1)), -1.0, 0.0)
TotalSignal = data['buysignal'].sum() + (data['sellsignal'].sum()*-1)
Tradingdays = data['Close'].count()
prob = (TotalSignal/Tradingdays)*100
print (Tradingdays)
print (TotalSignal)
print (prob)

Output of above program is


208
145
69.71

Out of 208 trading days 145 days HDFC closed above previous day close
price if open above previous day close price and closed below previous day
close price if open below previous day close price.
Probability = 145/208 * 100 = 69.71%
It means 2020 data says that there is 69.71% probability that HDFC will
close above previous day close price if open above previous day close price
and HDFC will close below previous day close price if open below previous
day close price.
You can download file in Excel thru following command to understand
how this program is computing probability –
data.to_csv("HDFC2020.csv", index=True, encoding='utf8')
You need to write additional 2 more commands if you are working in
Google colab and you wish to download data on your laptop.
from google.colab import files
files.download('HDFC2020.csv')

Sample data of csv file generated through above program code is given
below. If you will observe the data on 6th Jan 2020 HDFC open at 2428
lower than the previous day close price of 2454, same day HDFC close at
2384 it is also lower than the previous day close price. In the same way if
you will observe the data of 7th Jan 2020 HDFC open at 2401 and closed at
2415, both prices are higher than previous day closing of 2384.

Objective is to make money not to make complex strategies, so any


strategy which gives profit is a good strategy. 70% probability is a good
number to trade. Let’s compute profit generated by strategy in 2020.
Strategy is very simple –

1. If Open price is above previous day close price than investor


will buy HDFC in intraday when current trading price will be
equals to yesterday close price and investor will sell the positing at
end of the day.
2. If Open price is below previous day close price than investor
will sell HDFC contract when trading price will be equals to
yesterday close price and investor will buy the position at end of
the day.

Following python program could be used to compute the return of


strategy.
data['buyqty'] = np.where((data['Low'] < data['Close'].shift(+1)),
(data['Close']-data['Close'].shift(+1))*data['buysignal'], 0.0)
data['sellqty'] = np.where((data['High'] > data['Close'].shift(+1)),
(data['Close'].shift(+1) - data['Close'])*(data['sellsignal']*-1), 0.0)
data['profit'] = data['buyqty'] + data['sellqty']
Totalprofit = data['profit'].sum()
print(Totalprofit)
Output of the above program is 1551 it means trader will make money of
Rs 1551/- per share in 10 months if he traded on above intraday strategy. If
trader is trading derivative contract then profit earned by is Rs 4,65,300/- per
lot in first 10 months of 2020 (1551 multiplied by lot size of 300).
Back-testing on 1 year data is not sufficient. Back test this on data of
other previous years also to check the results. We are discussing here the
basic concepts. We will discuss strategies later on in this book.
Standard Deviation & Variance
Variance measure how far a set of numbers are spread out from their
average. Variance is calculated by taking the differences between each
number in the data set and the mean, following are the steps –

1. Finding the mean (the average).


2. Subtracting the mean from each number in the data set and
then squaring the result. The results are squared to make the
negatives positive. Otherwise negative numbers would cancel out
the positives in the next step. It’s the distance from the mean that’s
important, not positive or negative numbers.
3. Averaging the squared differences.

The standard deviation measures the dispersion of a dataset relative to its


mean. Standard deviation is calculated as the square root of the Variance. A
low standard deviation indicates that the values tend to be close to the
mean value of the set, while a high standard deviation indicates that the
values are spread out over a wider range. Standard deviation is the statistical
measure of market volatility, measuring how widely prices are dispersed
from the average price.
We can compute standard deviation in python through command stdev().
Let’s compare the standard deviation of 2 different data sets for better
understanding –
sample1 = [99,100,101]
sample2 = [90,100,110]
print (statistics.stdev(sample1))
print (statistics.stdev(sample2))

Output of above command will be –


1
10

Mean value of both sample is 100 but 1st sample have standard deviation
of 1 and second sample have standard deviation of 10. So the values in
sample2 are more widely dispersed from the mean value in compare to
sample1.
For traders it’s important to understand the probabilities associated with
certain multiples of standard deviations:
- 1 standard deviation includes approximately 68.2% of outcomes
- 2 standard deviations includes approximately 95.4% of outcomes
- 3 standard deviations includes approximately 99.7% of outcomes in a
distribution of occurrences
One standard deviation covers 68.2% of the values. It means there is
68.2% probability that next value will be within range of +- 1 standard
deviation from mean value.
The volatility of a stock is synonymous with one standard deviation of
daily returns (annualized) in that stock. You can check the volatility of any
Future Contract from Exchange Website.
For NSE > Open stock quotes > Derivatives > Nifty Future

As you can check above image daily volatility of Nifty Future is 1.85
and annualized volatility is 35.30. Nifty closing price is 11122. Given this
information you predict likely range within which nifty will trade 1 year
from Now –
Upper range = 11122 + 35.3% of 11122 = 11122 + 3926 = 15048
Lower range = 11122 – 35.3% of 11122 = 11122 – 3926 = 7196
Statistically speaking, there is 68% probability that Nifty will remain in
the range of 7200 to 15000 for next 1 year.
In the same way you can compute the monthly range also. You have
daily volatility of 1.85%. There are 30 days to expiry.
30 days Standard Deviation = 1.85 multiplied by Square root of 30 =
1.85 * 5.47 = 10.11%
Upper range = 11122 + 10.11% of 11122 = 11122 + 1124 = 12246
Lower range = 11122 – 10.11% of 11122 = 11122 – 1124 = 9988
Data suggest that there is 68% probability that Nifty is likely to trade
anywhere in the range of 9988 to 12246 for next 1 month.
Standard deviation works better in a normal distributed data. However,
closing prices of the stock you are trading may not be normally distributed.
You can easily see that running the code below -
data['Close'].hist(bins=100, figsize=(8, 6))

Here is how normal distribution should looks like -


So if close price data of stock is not normally distributed (it will be true
in most of the cases) then probability of falling 68% of values with in +- 1
standard deviation may not true. So you cannot trade only based on standard
deviation.
Bollinger Band
Bollinger Bands are envelopes plotted at a standard deviation level above
and below a simple moving average of the price. Because the distance of the
bands is based on standard deviation, they adjust to volatility swings in the
underlying price. Bollinger Bands use 2 parameters, Period and Standard
Deviations. The default values are 20 for period, and 2 for standard
deviations, although you may customize the combinations.
As we have computed moving average of last 10 trading days earlier, in
the same way we will compute 1.5 standard deviation of lat 10 days closing
prices to draw the Bollinger band of USDINR.
Following commands in Python can be used –
# Compute standard deviation of last 10 days closing prices
data['Stdav'] = data['Close'].rolling(window=10, min_periods=1,
center=False).std()
data['Upper_Band'] = data['Moving_average'] + (data['Stdav'] * 1.5)
data['Lower_Band'] = data['Moving_average'] - (data['Stdav'] * 1.5)

# Show Bollinger Band


data[['Close', 'Moving_average', 'Upper_Band',
'Lower_Band']].plot(figsize=(18,6))

You will get the following output. Statistically 68% values should remain
within the range of +- one standard deviation from the mean value, so if
price is touching upper band or lower band than they should come back to
mean value but mean value is also moving up or down with the prices that’s
why in range bound market price reverse to mean value will be true but in
case of trending market this will not be true. In a trending market price
touching upper band or a lower band may be a breakout upside or downside
respectively. You can observe in following chart also when January to April
when price was trending prices not reverse to mean value however from
April to October when Stock prices were range bound so price reverse to the
mean value.
Trading with Bollinger Bands-

Some investors trade with the help of Bollinger bands. Again which
moving average to use for computation of upper band and lower band is a
very subjective decision and it may depend on contract you are trading. Let’s
backtest the returns given by Bollinger Band with the help of historical data.
Backtesting on Google spreadsheet or Excel is going to be a very time
consuming activity so again lets do it with the help of Python codes you can
run on Google colab easily. I have written following codes in which one can
define stock, years, moving averages period for computation of moving
average and standard deviation to get returns. With the help of following
code I am computing yearly return given by Reliance Industries during the
year 2016 to 2020 on different combinations of moving average crossovers
from 1 to 35 and different multiplier factors of Standard Deviation. Basic
idea is to buy stock when price going below lower band in the hope that
price will come back to mean value and sell stock when price going above
upper band in the hope that prices will come back to mean values.
Following are the python codes –
!pip install yfinance
from datetime import datetime
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import yfinance as yf
Stock = "RELIANCE.NS"
data = yf.download(Stock, start="2016-01-01", end="2020-10-31")
T3 = pd.DataFrame({"Close": data["Close"]})
T3['Year'] = T3.index.year
T2 = pd.DataFrame({"cumpnl":['0'], "MA":['0'], "STD":['0'], "Stock":
['0'], "Year":['0']})
for z in range (2016, 2021, 1):
T = T3.where(T3.Year == z)
T = T.dropna()
for a in range(1,37,2):
for b in range(1,3,1):
MA=a
STD=b
T['moving_average'] = T.Close.rolling(MA).mean()
T['moving_std_dev'] = T.Close.rolling(MA).std()
T['upper_band'] = T.moving_average + (T.moving_std_dev*STD)
T['lower_band'] = T.moving_average - (T.moving_std_dev*STD)
T['positions_long'] = np.nan
T['positions_short'] = np.nan

for x in range (len(T)):


if T.Close[x] < T.lower_band[x]:
T['positions_long'][x] = 1
if T.Close[x] >= T.moving_average[x]:
T['positions_long'][x] = 0
if T.Close[x] > T.upper_band[x]:
T['positions_short'][x] = -1
if T.Close[x] <= T.moving_average[x]:
T['positions_short'][x] = 0
T.positions_short = T.positions_short.fillna(method='ffill')
T.positions_long = T.positions_long.fillna(method='ffill')

T['positions'] = T.positions_long + T.positions_short


T['price_difference']= T.Close - T.Close.shift(1)
T['pnl'] = T.positions.shift(1) * T.price_difference
T['cumpnl'] = T.pnl.cumsum()
T1 = T[['cumpnl']].tail(1)
T1['MA'] = MA
T1['STD'] = STD
T1['Stock'] = Stock
T1['Year'] = z
T2 = T2.append(T1)

Pivot_Table1 = pd.pivot_table(T2, values ='cumpnl', index =['MA',


'STD'], columns =['Year'], aggfunc = np.sum)

Pivot_Table1.to_csv("PV_T.csv", index=True, encoding='utf8')


from google.colab import files
files.download('PV_T.csv')
Following is the out of above program for Reliance Industries. As you
can observe in most of the year values are in negative. Highest loss is in year
2020 with all combinations of moving averages and standard deviations
because prices of Reliance were trending during this period. Bollinger Band
will give you profit when prices will be mean reverting and mean value will
remain constant. So trading of mean reversal strategy with Bollinger bands
are profitable if stock prices are range bound.

However, in trending market you can do just opposite. It means, you are
buying when price going above upper band and selling when stock prices
going below lower band. If anyone has traded Reliance this way buying
when price going above upper band and selling when price going below
lower band and both side bands are created with 3 days moving average and
1 standard deviation then profit was 329, 516, 282, 518 from 2017 to 2020
respectively as per following screen shot.
Let’s try this on strategy on range bound stock. Following is the output
when we tried this strategy on historical prices of NTPC. With the following
it can be observed that results of 4 days moving average with bands on
distance of 1 standard deviation are consistently profitable if trader is buying
when price goes below lower band and sell when price goes above upper
band.
Correlation
Correlation is a statistical technique that can show whether and how
strongly pairs of variables are related. When two sets of data are strongly
linked together we say they have a High Correlation. Correlation
is Positive when the values increase together, and Correlation
is Negative when one value decreases as the other increases.
Correlation is quantified by the correlation coefficient ρ, which ranges
from -1 to +1. The correlation coefficient indicates the degree of correlation
between the two variables. The value of +1 means there exist a perfect
positive correlation between the two variables, -1 means there is a perfect
negative correlation and 0 means there is no correlation.

The correlation coefficient for the two variables is given by

Correlation(X,Y) = COV(X,Y) / SD(X).SD(Y)

Where, cov (X, Y) is the covariance between X & Y while SD (X) and
SD(Y) denote the standard deviation of the respective variables.

In Google Sheet following formula can be used for computation of


correlation among 2 data series –

=CORREL (data1, data2)

In Python following code can be used –

from scipy.stats import pearsonr


data = yf.download('HDFC.NS', start="2016-01-01", end="2020-10-30")
data1 = yf.download('HDFCBANK.NS', start="2016-01-01",
end="2020-10-30")
corr = pearsonr(data['Close'], data1['Close'])
print (corr)
Please observe the above screen shot, you can check that we have taken
last 5 years data of HDFC and HDFC bank from 1st January 2016.
Correlation among HDFC and HDFC Bank is 0.96. It means we can say
both stocks are highly correlated.

Trader can also plot chart of both data series and can observer the price
behavior of both of the data series. One of the best ways to visually depict
the relationship between two variables is by using a scatter plot. We can use
the following code for Scatter diagram –
from matplotlib import pyplot
pyplot.scatter(data['Close'], data1['Close'])
pyplot.show()
In this plot, blue dots represent the different points where HDFC Bank
prices given on Y axis and HDFC prices are given on X axis. As most points
lie around the blue line, it is an indication that a linear relationship might
indeed exist between HDFC and HDFC Bank.

We can use the following codes for price chart of both stocks on different
axis –

fig,ax = plt.subplots(figsize=(18,6))
ax.plot(data['Close'], color="red")
ax2=ax.twinx()
ax2.plot(data1['Close'],color="blue")
plt.show()
Output of above code is given in the next screen shot. Please observe the
chart for HDFC prices with red line refer left side prices and HDFC Bank
prices with blue line refer right side prices.
LINEAR REGRESSION
As a pair trader we want to forecast the future prices of stocks we are
observing with a reasonable degree of confidence. This brings us to
regression.

In regression, a function is created which helps in analyzing the


relationship between variables and also in predicting one variable based on
its relationship with other variables. The variable which is predicted is
known as the dependent variable and is generally denoted by Y, and the
variables which have an impact on the dependent variable are known as
independent variables and are generally denoted by X. The most common
method for fitting a regression line is the method of least-squares. This
method calculates the best-fitting line for the observed data by minimizing
the sum of the squares of the vertical deviations from each data point to the
line.

The linear model we are looking for is of the form:

Y=a+bx+e

[a + b x] is the “regression function. In this function a and b are constant.


Data points might not fit the function exactly but the aim is to get as close as
possible. So ‘e’ is the error term. The regression function contains all
information regarding the two variables while the error term is the error in
prediction which is represented by green lines, data points represented by red
dots and underlying relationship is represented by blue line in the following
figure:
The good news is that Regression tools are available in Excel. For that
first you need to download these tools in Excel.

Click on Add-Ins and download Analysis ToolPak.

Now you will get Regression tools in Data > Data Analysis > Regression
as shown in following screenshot –
As we have fetched past data from Google finance in Google spread
sheet. We have downloaded this data in Excel. Now we can perform
‘Regression’ function on this data.
We will get the following output –

Let us interpret this result.

In this table, we can see the actual estimated values for the intercept and
the slope.
Thus, the model is: (Price of HDFC) = 394.89 + 1.455 *(HDFC Bank)

R is the percentage of variation in the data that is explained by our


model. Its value lies in the range of 0 to 1. Higher the value of ‘R’ higher the
accuracy of the model. As the R square value is 0.9674, the model is able to
explain almost 96% of the variation i.e. the price of HDFC Bank is able to
explain a high degree of variation in the price of stock HDFC.

Standard Error is 86.29, this is standard deviation of residual/error (error


‘e’, as explained in above function with green line). Residual are plotted in
the above chart, as we can see range is approx +300 to -300 and standard
deviation of these number is 86.29. The standard error determines level of
variability associated with the estimated values of variables. Accuracy of the
model is more when the standard errors are less.
t-stats and p-values: t-stats here are the statistic values for a hypothesis
tests conducted using the t-statistic for each estimated coefficient and the
intercept. Here the test is to find whether the estimated values of ‘a’ and ‘b’
are significantly different from zero on an individual level. The
corresponding p-values for the tests are also reported. Generally, a model
with p-values less than 0.05 is desirable as it indicates that the estimated
values for ‘a’ and ‘b’ are reliable. The p-values in above table for both the
intercept and the slope are very small (<0.05), leading to the statistical
significance of the values obtained.

Thus, a data driven trader can decides to use the price of HDFC Bank as
an important variable while designing a strategy to trade stock HDFC. Value
of ‘b’ is also called beta value. Value of ‘b’, 1.455 can be used as hedge ratio
for pair trading. It means if trader is buying 10 share of HDFC then he
should sell 15 shares of HDFC Bank. I am not in favor of using beta value as
hedge ratio in parity trading. I will explain my view of hedge ratio later in
this book.
Stationary Time Series
This is the most important concept to understand for traders. Before
going into deep details of statistical tools you must have an idea of price
behavior of instruments you are trading. First we understand this concept.
‘A stationary time series is one whose statistical properties such as mean,
variance, autocorrelation, etc. are all constant over time.’ So you can say that
if prices of a stock are range bound then it’s a stationary data and if prices
are trending upwards or downwards then it’s a non-stationary data. A time
series is stationary if it reverses to mean values.
Trading using statistical tools includes –

1. Directional Trading
2. Pair Trading

If price is stationary we can trade mean reversal strategy. It will be


difficult to find individual stock stationary but combination of 2 stocks,
portfolio could be stationary with one long and one short. If data is non-
stationary then directional trading strategies will be profitable.
In pair trading, you are trading price difference of 2 stocks so you need
to check whether this price difference is stationary or non-stationary. For
pair trading traders need to find time series which are stationary. Let us
continue with our previous example of HDFC Bank and HDFC. With the
following python codes we are plotting price difference of 2 stocks from
2016 on a chart.
data['Close']-data1['Close']).plot(figsize=(18,6))
plt.axhline((data['Close']-data1['Close']).mean(), color='red', linestyle='--
')
plt.xlabel('Time')
plt.legend(['Price Difference', 'Mean'])
plt.show()

If you will observe the following price difference chart of HDFC and
HDFC Bank you will notice that difference in prices of both stocks was
approx 550 at beginning of year 2016 and this price difference goes up to
900 till beginning of year 2018. So you can say there was a slight upper
trend during this period. From beginning of 2018 to mid 2019 prices are
coming back to the mean value. There was a rollercoaster ride in price
difference during mid of 2019 to mid of 2020. Theoretically speaking, Just
to explain a thought, assume anyone who has created a position of pair
trading at 900 somewhere in beginning of 2020 with an hope that difference
will come down to mean value of 800 has seen MTM loss of 300 points
when this difference goes upto 1200 points in a month or so. There was risk
of permanent shifting of mean value also from 800 to 1200. That is why
some stop loss always required in pair trading. I don’t have past data
analysis in support of my statement but I believe that It’s always better to
book loss exit the position if things are going in adverse direction beyond a
certain point. That’s why we need a system that can address the above issue.
You can address this issue by taking rolling mean (moving average) period
as low as possible. This will give you quick entry and quick exit. You will
not see big mark to market losses but this will increase the cost of trading
because buy sell signal will be higher. In the following chart we have taken a
fixed mean value that is constant over 5 years.

Instead of going for the visual test, we can use statistical tests like ADF
(Augmented Dickey Fuller) Test. The Dickey Fuller test is one of the most
popular statistical tests. It can be used to determine the presence of unit root
in the series, and hence help us understand if the series is stationary or not.
Following commands can be used –
from statsmodels.tsa.stattools import adfuller
adf = adfuller(data['Close']-data1['Close'], maxlag = 1)
print (adf[0])
print (adf[1])
print (adf[4])

Running the example prints the test statistic value of -3.31. The more
negative this statistic, the more likely we have a stationary dataset. We can
see that our statistic value of -3.31 is less than the value of -2.86 at 5%. The
p-value is obtained is less than significance level of 0.05. p-value in the
above test is 0.0135 it means there is 98.65% (100-1.35%) chance of time
series being stationary. This suggests that we can reject the null hypothesis,
rejecting the null hypothesis means that the time series is stationary.
Z-Score
The Z-score is the number of standard deviations that the pair ratio has
diverged from its mean. For a pair that is co-integrated, you will typically
see the Z-score bounce around 0.

Z-Score = (X - Mean(X)) / Standard Deviation(X)

Z-score is used in pair trading for entry and exit signals. Once the trade
is entered one just waits for the Zscore to mean revert. A trade is executed
when: 1. The spread goes less than -2 Z-score(z-score < -2 ) we long on the
pair (buy y, short x) and exit the position if it hits -1 Z-score (z-score > -1) 2.
The spread goes greater than 2 Z-score(z-score > 2 ) we short on the pair
(buy y, short x) and exit the position if it hits +1 Z-score (z-score < +1) So
basically we initiate a trade when the z-score exceeds +2/-2 and exit the
trade when it drops below +1 and above -1. Trade can be initiated when the
z-score exceeds +1/-1 (it depends on instrument you are trading), exit the
trade when it comes back to zero.
There would be lot of drawdown if the pairs do not start to mean revert
immediately. If you are taking beta as a hedge ratio it will be better to run
the linear regression on the 2 stocks every day and measure the stock daily
position size based on the new beta value for that day. Sell or buy more of
the Long stock so that the hedge is maintained on daily basis. This helps in
reducing the volatility in the portfolio and drawdown is reduced. And once
the Z-score mean reverts close both the trades.
Pair trade backtesting setup in Google
Spreadsheet
If two companies are similar, operate in the same
sector/country/conditions then their stock prices tend to move together. We
check this relation with statistical tools like correlation, ADF test etc. as
discussed earlier. Any change in the business landscape will affect the stock
prices of both the companies. If stock price of one company deviate away
from the stock price of the other without any event/incident then on such
days, the price difference of both of the companies deviates. We look for
such deviations to identify good trading opportunities. When such deviations
arise we take long position in one stock and short position in another then we
wait for the pair to move towards the mean value of price difference. We
need to stay long and short of the same Rupee/Dollar value. This is also
called ‘Rupee/Dollar Neutrality’. It means value of long position (price
multiplied by quantity) should be equals to the value of short position.
Before implementing any strategy we should backtest our logics on past data
to check the profitability. For a trader most important thing is the profit.
While getting into the technicalities of math and stats one should not forget
that ultimate objective is profit. So we will set up a Google spreadsheet to
backtest strategy on different parameters. (You can download this spread
sheet from Github. Link is given at end of this book.)

1. We have a Google spread sheet opened in a browser. We are


fetch historical data from Google Finance with the help of
following formula in a cell of spread sheet –

GoogleFinance(Symbol, Attribute, Start Date, End Date, Interval)

Please refer the following screen shot. We have taken daily closing
price of HDFC and HDFC Bank from 1 January 2016 to 30th October
2020 in column ‘C’ and column ‘F’ respectively.

2. We are computing Spread (difference in Stock prices of both


stocks) in column ‘H’.
Spread = HDFC Close Price – HDFC Bank Close Price

3. Moving average (Rolling mean value) of Spread is computed


in column ‘I’. We are taking last 5 trading days Spread prices for
computation of mean value with the help of following formula.

=AVERAGE(H11:H15)

4. We are computing Moving Standard Deviation of Spread in


column ‘J’. We are taking last 5 trading days Spread prices for
computation of standard deviation with the help of following
formula.

=STDEV(H11:H15)

5. Upper Band is computed in column ‘K’ with the help of


following formula –

Upper Band = Mean (moving average) + Standard Deviation

6. Lower Band is computed in column ‘L’ with the help of


following formula –

Lower Band = Mean (moving average) - Standard Deviation


7. In the column N we are generating signals of long entry with
the help of following formula –

Long Entry =if(H12<L12,"T","F")

This formula will return ‘T’ in cell ‘N12’ if value in cell ‘H12’
(Spread) will be lower then value in cell ‘L12’ (Lower Band). If value
will be higher than this formula will return ‘F’. If you will observe the
following screen shot you will find value ‘T’ in column ‘N12’ because
spread price 643.23 is lower than the Lower Band price 648.56.

8. In the column ‘O’ we are generating signals of long exit with


the help of following formula –

Long Exit = if(H12>=I12,"T","F")

Above formula will return ‘T’ when Spread value will be higher
than or equals to the mean value.

9. So in column ‘N’ Excel is generating a signal of buy when


spread price will go below lower band price and column ‘O’ will
generate a signal to exit the position when price will come back to
its mean value. With the help of following formula we are taking
numeric values in column ‘P’.

Position Long = if(N12="T",1,If(P11=1,IF(O12="T",0,1),0))

If output of the above formula is 1 then it means we are having long


position in spread.

10. As we have generated long signals with the help of above


formulas in the same way are generating short signals in column
‘R’, ‘S’, ‘T’ with the help of following formulas –

Short Entry = if(H12>K12,"T","F")


Short Exit = if(H12<=I12,"T","F")
Position Short = if(R12="T",-1,If(T11=-1,IF(S12="T",0,-1),0))

11. Net position in column ‘V’ is computed by adding values of


column ‘P’ and column ‘T’. Value of 1 in this column means we
have long position and -1 in this column means we have short
position. 0 means no position on that day.

Net Position = Position Long + Position Short

12. ‘Price Difference’ of Spread with previous day price is taken in


column ‘W’, P&L in column ‘X’ arise by multiplying Price
Difference and Net Position. In last column ‘Y’ we have
cumulative profit and loss.

Our Google Excel Spreadsheet is ready to compute returns of any


combination of stock. Change the stock Symbol and sheet will compute
past period pair trading returns of given combination of stocks. You can
change moving average and standard deviation period also and can
compute the returns for a given rolling period. This strategy has
generated a return of Rs 1782/- per share in last 5 years.
Pair trade backtesting in Python
As we have done computation of Google spread sheet, program code of
python for the same is given below. We are taking past 5 years close price of
HDFC and HDFC bank in a separate table ‘prices_df’ for computation of
returns on past data. With the following python codes you can observer the
change in difference of prices of both stocks along with prices of both stocks

prices_df = pd.DataFrame({"Stock_1": data["Close"], "Stock_2":
data1["Close"]})
prices_df['Diff'] = prices_df['Stock_1'] - prices_df['Stock_2']
prices_df[['Stock_1', 'Stock_2', 'Diff']].plot(grid=True,
secondary_y='Diff', figsize=(14,6))

You will get the following output. You can observe that price difference
among both stocks is increasing with rise in prices (difference is plotted right
side and for stock prices please refer left side axis.)

Now we will take following steps for computation of returns-

1. First we will compute the moving average of difference in


prices of both stocks. As we discussed earlier its better to moving
average period as shot as possible. So we are computing 5 days
moving average.
2. We are also computing 5 days standard deviation of difference
in prices of both stocks.
3. As we know 1 standard deviation covers 66% of the values. It
means if price difference will move more than 1 standard deviation
from its mean value then there will be high probability that price
will revert to its mean value.
4. So we are computing upper band with mean value + standard
deviation and lower band with mean value – standard deviation.
5. We will create a short position when price difference will cross
upper band and we will square off the position when this will
come back to mean value. We will create a long position when
price difference will cross the lower band and square off the
position when price difference will come back to its mean value.

So lets compute moving average of standard deviation with 5 days


rolling period and upper band and lower band.
prices_df['moving_average'] = prices_df.Diff.rolling(5).mean()
prices_df['moving_std_dev'] = prices_df.Diff.rolling(5).std()
prices_df['upper_band'] = prices_df.moving_average +
prices_df.moving_std_dev
prices_df['lower_band'] = prices_df.moving_average -
prices_df.moving_std_dev
prices_df[['Diff', 'moving_average', 'upper_band',
'lower_band']].plot(figsize=(16,6))

Output of above code will look like this-


Above chart is not much clear. You can use plotly python library for
interactive charts. Following code will give you better chart that you can
zoom in and zoom out for better visualization –
import plotly.express as px
Table = prices_df[['Diff', 'moving_average', 'upper_band', 'lower_band']]
fig = px.line(Table)
fig.show()

We have computed upper band and lower band. Following python code
will compute profit on loss of strategy –
prices_df['positions_short'] = np.nan
prices_df['positions_long'] = np.nan

for x in range (len(prices_df)):


if prices_df.Diff[x] < prices_df.lower_band[x]:
prices_df['positions_long'][x] = 1
if prices_df.Diff[x] >= prices_df.moving_average[x]:
prices_df['positions_long'][x] = 0
if prices_df.Diff[x] > prices_df.upper_band[x]:
prices_df['positions_short'][x] = -1
if prices_df.Diff[x] <= prices_df.moving_average[x]:
prices_df['positions_short'][x] = 0
prices_df.positions_long = prices_df.positions_long.fillna(method='ffill')

prices_df.positions_short =
prices_df.positions_short.fillna(method='ffill')

prices_df['positions'] = prices_df.positions_long +
prices_df.positions_short
prices_df['price_difference']= prices_df.Diff - prices_df.Diff.shift(1)
prices_df['pnl'] = prices_df.positions.shift(1) * prices_df.price_difference
prices_df['cumpnl'] = prices_df.pnl.cumsum()

prices_df[['cumpnl']].plot(figsize=(16,8))

You will get following output of above program. In this strategy


‘cumpnl’ is the cumulated profit and loss of the strategy. Cumulative profit
on this strategy is Rs 1700/-. It means trader earned 1700 per share.

We also need to check drawdown in any strategy. Following python


codes can be used to compute the drawdown.

# Calculate the max drawdown in the past window days for each day
prices_df['rolling_max'] = prices_df['cumpnl'].rolling(250,
min_periods=1).max()
prices_df['daily_drawdown'] = prices_df['cumpnl']-
prices_df['rolling_max']

# Calculate the minimum (negative) daily drawdown


prices_df['max_daily_drawdown'] =
prices_df['daily_drawdown'].rolling(250, min_periods=1).min()

fig, axs = plt.subplots(2,figsize=(15,8))


axs[0].plot(prices_df['cumpnl'])
axs[1].plot(prices_df['max_daily_drawdown'])

You will get the following output. Maximum drawdown in the strategy is
approx 200 points.

We can do further analysis of strategy performance like total number of


trade count, maximum profit in a trade, maximum loss in a trade etc.
Following code can be used for computation –

prices_df['Trade'] = prices_df['positions'].diff()
T1 = prices_df.where((prices_df.Trade != 0))
T1 = T1.dropna()
T1.drop(["moving_average", "moving_std_dev", "upper_band",
"lower_band", "positions_long", "positions_short", "price_difference", "pnl",
"rolling_max", "daily_drawdown", "max_daily_drawdown"], axis = 1,
inplace = True)
T1['Trade_Return'] = (T1['cumpnl'].diff()/T1['Diff'])*100
print ("Number of Trade count", round(len(T1)/2))
T1[['Trade_Return']].plot(figsize=(16,8))

You will get the following output. Total numbers of trade done by
strategy was 193. You can observe the maximum retrun generated by each
trade in following chart. As you can observe maximum loss was approx 15%
in a single trade and maximum retrun was approx 20% in a single trade.

You can also download data in excel with following command for further
analysis -

T1.to_csv("Strategy_Analysis.csv", index=True, encoding='utf8')

Most of the people use ‘Z score’ of ratio (Stock 1 / Stock 2) to generate


signals for trading spread. However I have taken only spread (difference in
prices) for all computation. If you will use ‘z score’ then also the results will
be almost similar. It will not happen that computation with spread will give
you x profit and computation with ratio will give you 2x profit, if data and
period is same then results of both will remain almost similar. Even if you do
some optimization by creating more complex tools for more profit, this
optimization will be on past data and there is no guarantee that optimized
things will perform better in future also. Complexity of tools does not give
you more profits. Try to keep the things as simple as possible. When you
observe the price of both stocks you can compute the spread (price
difference) without any tool or computation. You have an idea of past
spreads also, for example we have seen difference in price of HDFC and
HDFC bank was in the range of 600 to 1200 in last 5 years. We are trading
for a profit of 50 or 100 so if this spread is going against us then we should
take some stop loss of say 100. We can check this spread is going in favor or
against after creating a spread position just by watching live prices on
screen. So trading with spread is easy to understand and need not any
complex computations.
If you want to optimize things for more profit then optimize days. How
many days we should take for computation of mean value and standard
deviation? I have taken 5 days in above example you can compute profit
with 4 days or 6 days or may be 10 days. One thing you will observer while
backtesting on past data that if you will take bigger period for mean value
and standard deviation then drawdown’s will be big. Strategy will give you
big profits and big losses. We have taken period of 5 days in above example
because I observed that prices are mean reverting in short period, however
with long period trending strategies are more profitable. So I believe we
should trade mean reverting strategies with lowest possible short period data.
You can form your opinion with your experience; try more and more
backtesting of pair trading with different combinations in different assets
class. Do not rely 100% on mathematics, earn your own experience. This
experience will help you to take better decisions not mathematics.
Pair trade backtesting of multiple stocks on different
moving averages in Python
We learned to find trading opportunities of pair trading between two
stocks of same sector. Many stocks in same sectors are available for trading
we can try to find pair trading opportunities among all stocks by comparing
stocks on one to one basis. Following codes can be used for computation of
yearly profit of pair trading generated by different combinations of private
banks from 2016 to 2020. With the help of following codes we are
computing returns generated by different combination of pairs of 6 private
sector banking stocks on different moving averages from 1 to 14.
# Import necessary libraries
!pip install yfinance
from datetime import datetime
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import yfinance as yf
from scipy.stats import pearsonr
from numpy import mean
from numpy import std
from statsmodels.tsa.stattools import coint, adfuller
import seaborn as sns

# Fetch historical data


data = yf.download('HDFC.NS', start="2016-01-01", end="2020-10-31")
data1 = yf.download('HDFCBANK.NS', start="2016-01-01",
end="2020-10-31")
data2 = yf.download('ICICIBANK.NS', start="2016-01-01", end="2020-
10-31")
data3 = yf.download('KOTAKBANK.NS', start="2016-01-01",
end="2020-10-31")
data4 = yf.download('INDUSINDBK.NS', start="2016-01-01",
end="2020-10-31")
data5 = yf.download('AXISBANK.NS', start="2016-01-01", end="2020-
10-31")
# Computation of correlation, co-integration between all stocks
abc = ["HDFC", "HDFCBK", "ICICIBK", "KOTAKBK",
"INDUSINDBK", "AXISBK"]
prices_df = pd.DataFrame({"HDFC": data["Close"], "HDFCBK":
data1["Close"], "ICICIBK": data2["Close"], "KOTAKBK": data3["Close"],
"INDUSINDBK": data4["Close"],
"AXISBK": data5["Close"]})
for aa in range(len(abc)):
for bb in range(aa,len(abc)):
if aa==bb: continue
Cointegration = coint(prices_df[abc[aa]],prices_df[abc[bb]])[0]
correlation = pearsonr(prices_df[abc[aa]],prices_df[abc[bb]])
ADF = adfuller(prices_df[abc[aa]] - prices_df[abc[bb]], maxlag = 1)
[1]
print(abc[aa],abc[bb],"Cointegration",Cointegration,"correlation",cor
relation,"adfuller",ADF)

# You will get the following output of above commands -

# Computation of yearly profits generated by different pairs


prices_df['Year'] = prices_df.index.year
T2 = pd.DataFrame({"cumpnl":['0'], "Stock1":['0'], "Stock2":['0'],
"Moving_average":['0'], "Year":['0']})
for z in range (2016, 2021, 1):
T = prices_df.where(prices_df.Year == z)
T = T.dropna()
for x in range(len(abc)):
for y in range(x,len(abc)):
if x==y: continue
for w in range(1,16,1):
T['Diff'] = T[abc[x]]-T[abc[y]]
T['moving_average'] = T.Diff.rolling(w).mean()
T['moving_std_dev'] = T.Diff.rolling(w).std()
T['upper_band'] = T.moving_average + T.moving_std_dev
T['lower_band'] = T.moving_average - T.moving_std_dev
T['positions_long'] = np.nan
T['positions_short'] = np.nan

for r in range (len(T)):


if T.Diff[r] < T.lower_band[r]:
T['positions_long'][r] = 1
if T.Diff[r] >= T.moving_average[r]:
T['positions_long'][r] = 0
if T.Diff[r] > T.upper_band[r]:
T['positions_short'][r] = -1
if T.Diff[r] <= T.moving_average[r]:
T['positions_short'][r] = 0

T.positions_short = T.positions_short.fillna(method='ffill')
T.positions_long = T.positions_long.fillna(method='ffill')
T['positions'] = T.positions_long + T.positions_short
T['price_difference']= T.Diff - T.Diff.shift(1)
T['pnl'] = T.positions.shift(1) * T.price_difference
T['cumpnl'] = T.pnl.cumsum()
T1 = T[['cumpnl']].tail(1)
T1['Stock1'] = abc[x]
T1['Stock2'] = abc[y]
T1['Moving_average'] = w
T1['Year'] = z
T2 = T2.append(T1)

# Pivot table with values of cumulative profit and loss created


Pivot_Table1 = pd.pivot_table(T2, values ='cumpnl', index =['Stock1',
'Stock2', 'Moving_average'],
columns =['Year'], aggfunc = np.sum)
print (Pivot_Table1)

# Pivot table data downloaded


Pivot_Table1.to_csv("PV_T.csv", index=True, encoding='utf8')
from google.colab import files
files.download('PV_T.csv')

You will get the following output of above program codes. If you
observe the following output you will notice that pair trading among HDFC
and HDFCBANK with computation of 7 days moving average and moving
standard deviation is consistent every year since 2016.

Pair trading combination of HDFC and HDFC Bank was profitable with
all moving averages most of the time however if you will check data in
above table pair trading of HDFC Bank and ICICI bank was not much
profitable. Past data says in trading of this combination it will be difficult to
cover cost.
Machine Learning for Pair Trading
We learned to find trading opportunities of pair trading between two
stocks of same sector. Many stocks in same sectors are available for trading
and if you will try to find pair trading opportunities among all stocks by
comparing stocks on one to one basis then it’s going to be a very time
consuming task. Now let us build a model based on pair trading where a
program code can find the most expensive stock to sell and cheapest one to
buy out of a basket of many stocks. Principal component analysis will make
our task easy.
Principal Component Analysis(PCA) is an unsupervised statistical
technique used to examine the interrelation among a set of variables in order
to identify the underlying structure of those variables. Suppose we have 100
stocks in basket then we have much more complex data and therefore
identifying and predicting a dependent factor against so many independent
factors can reduce the probability of getting a correct prediction. That is why
it is important to identify strong independent variables. Dimensionality
Reduction is a technique that allows us to understand the independent
variables and their variance thus helping to identify a minimum number of
independent variables that has the highest variance with respect to the
dependent variables. So the dimensionality reduction technique helps us
reduce the number to independent variables in a problem by identifying new
and most effective ones. It is also known as factor analysis.
In regression, we usually determine the line of best fit to the dataset but
here in the PCA, we determine several orthogonal lines of best fit to the
dataset. Orthogonal means these lines are at a right angle to each other.
Actually, the lines are perpendicular to each other in the n-dimensional
space.
PCA is a method of compressing a lot of data into something that
captures the essence of the original data. PCA takes a dataset with a lot of
dimensions and flattens it to 2 or 3 dimensions so we can look at it. PCA
creates new variables known as principal components. The 1st principal
component will try to explain the direction of the most variation. The 2nd
principal component will try to explain the remaining variability. Actually
these components are calculating the systematic risks. In our data, we apply
PCA on stock price/returns of various stocks. PCA plot converts the
correlations among all of the cells into a 2-D graph. We use PCA to find the
common risk factors of stock returns which is helpful to group pairs
accordingly using clustering algorithms.
Python program codes –
!pip install yfinance
from datetime import datetime
import yfinance as yf
from scipy import stats as stats
from scipy.stats import pearsonr
from numpy import mean
from numpy import std
import numpy as np
import pandas as pd
import statsmodels
from statsmodels.tsa.stattools import coint, adfuller
import matplotlib.pyplot as plt
import seaborn as sns; sns.set(style="whitegrid")
from sklearn.linear_model import LinearRegression
from sklearn.decomposition import PCA
from itertools import groupby, count
import statsmodels.api as sm
%matplotlib inline

# Download historical data


data = yf.download('HDFC.NS', start="2017-01-01", end="2018-12-12")
data1 = yf.download('HDFCBANK.NS', start="2017-01-01",
end="2018-12-12")
data2 = yf.download('ICICIBANK.NS', start="2017-01-01", end="2018-
12-12")
data3 = yf.download('KOTAKBANK.NS', start="2017-01-01",
end="2018-12-12")
data4 = yf.download('INDUSINDBK.NS', start="2017-01-01",
end="2018-12-12")
data5 = yf.download('AXISBANK.NS', start="2017-01-01", end="2018-
12-12")
# New table prices_df created with daily closing prices of all stocks
prices_df = pd.DataFrame({"HDFC": data["Close"], "HDFCBK":
data1["Close"], "ICICIBK": data2["Close"], "KOTAKBK": data3["Close"],
"INDUSINDBK": data4["Close"], "AXISBK": data5["Close"]})
prices_df.head()
abc = ["HDFC", "HDFCBK", "ICICIBK", "KOTAKBK",
"INDUSINDBK", "AXISBK"]
# ADF test for different combinations of stocks
for x in range(len(abc)):
for y in range(x,len(abc)):
if x==y: continue
print(abc[x],abc[y], "ADF", adfuller(prices_df[abc[x]] -
prices_df[abc[y]], maxlag = 1)[1])
def Zscore(X):
return np.array((X - np.mean(X)) / np.std(X))
stocks = 6
capital = 10000
components = 1
max_pos=1
S1 = []
L1 = []
i1 = []
pnls = []
dates = []
for i in range (len(prices_df)):
if i < 10: continue
prices = prices_df.iloc[0:i]
pr = np.asarray(prices.T)
pca = PCA(n_components=components)
comps = pca.fit(pr.T).components_.T
factors = sm.add_constant(pr.T.dot(comps))
mm = [sm.OLS(s.T, factors).fit() for s in pr]
resids = list(map(lambda x: x.resid, mm))
zs = {}
for inst in range(stocks):
zs[inst] = Zscore(resids[inst])[-1]
idx_long = (np.argsort([zs[j] for j in zs])[:max_pos])
idx_short = (np.argsort([zs[j] for j in zs])[-max_pos:])
L1.append(abc[int(idx_long)])
S1.append(abc[int(idx_short)])
dates.append(prices_df.index[i])
i1.append(i)
df = pd.DataFrame(i1, dates)
df['Long'] = L1
df['Short'] = S1
df = df.join(prices_df)
df['Long_P'] = 0
df['Short_P'] = 0
df['Profit'] = 0
df['Total_Profit'] = 0
for x in range ((len(df)-1)):
y = x+1
a = df['Long'][x]
b = df['Short'][x]
df['Long_P'][x] = (df[a][y] - df[a][x])*(round(capital/df[a][x]))
df['Short_P'][x] = (df[b][x] - df[b][y])*(round(capital/df[b][x]))
df['Profit'] = df['Long_P'] + df['Short_P']
df['Total_Profit'] = df['Profit'].cumsum()
plt.plot(df['Total_Profit'])

#you will get the following output (Chart of cumulative profit and loss) –

#Download daywise computations in Excel file


df.to_csv("pair_pca.csv", index=True, encoding='utf8')
from google.colab import files
files.download('pair_pca.csv')

You will get the following output. As you can observe the data in Excel
sheet (following screen shot) on 16th Jan 2017 system generated buy signal
in Indusind Bank and sell signal in HDFC. On 18th Jan 2017 sell signal
generated in Axis Bank so trader will buy HDFC and sell Axis Bank. After
this trader will have long position in Indusind Bank and short in Axis Bank.
On 20th Short position shifted from Axis Bank to ICICI Bank and so on. At
any given point of time trader will have long position in 1 stock and short
position in 1 stock out of 6 stocks taken for pair trading.
Strategy has given a profit of 10,000/- on investment of Rs 10,000 in
each stock.
Python Codes @ GITHUB

You can download Python codes given in this book in Jupyter notebook
from github. Link to the Github account is given below -
https://github.com/OptionsnPython/Trading-Pairs
About Authors / Acknowledgments

Anjana Gupta, I am author of this book. I am having master degree in


science and management. I am having more than 10 years of experience.
Special thanks to Puneet Kanwar, who was instrumental in the completion
and editing of this book. Puneet Kanwar is having an experience of 15 years
in Indian capital market. He has worked with BSE Limited, formally known
as Bombay Stock Exchange, for 6 years. He has also worked with
prestigious broking house, Edelweiss prior to BSE. In 2017 Puneet resigned
from BSE for his own venture. Currently he is a successful option trader and
arbitrager.

If you found this book useful please give review on Amazon and
recommend this book in your network for benefit of all.

For feedback / suggestions / query / doubt you can write to me at


[email protected].

Linked in Profile: https://www.linkedin.com/in/anjana-gupta-28913a1b0/

Happy learning.
Anjana Gupta
Books By This Author

Option Greeks, Strategies & Backtesting in Python


his book is meant for investors and traders of NSE India.

The book is divided into three parts -

1. First part cover option Greeks - Delta, Gamma, Theta, Vega, Delta
hedging & Gamma Scalping, implied volatility with the example of past
closing prices of Nifty/USDINR/Stocks (Basics of Future and options
explain).

2. Second part covers option trading strategies with examples of


Nifty/USDINR options and computation of returns of a strategy on past data.
(You will get an idea how professional traders think)

3. Third part covers Python for traders. After reading this book a novice
trader will also be able to use python from installation of Anaconda on his
laptop & extracting past data to back-testing and development of his own
strategies. Python is explained from very basic so that anyone who does not
have in-depth understanding of programming can understand and develop
codes. Many program codes and their results also explained for back-testing
of strategies likes ratios, butterfly etc.
Books By This Author

Python For Trading On Technical: A step towards systematic


trading
This is a beginner’s guide on Python and Technical Analysis. This book will
help you to backtest your own ideas. One can easily backtest returns
generated by strategy on past data of various stocks with python codes. For
analysis of strategies - python codes given for computation of number of
trades, total profit, maximum draw down, Profit and loss on each trade,
computation of profit after considering cost of trade.

This book will cover following –


1. Basics of Python - Python is also explained from very basic so that
anyone who does not understand programming can write and develop his
own codes from fetching free historical data to back testing of own
strategies.
2. Basics of Technical Analysis - Technical Analysis is explain from very
basic, most of the popular indicators used in technical analysis explained.
Python program codes are also given with each indicator so that one can
learn to backtest.
3. At end, How to develop a trading setup with mix of various technical
indicators explained.

The book will explain multiple trading strategies with python codes to get
you well on the path to becoming a professional systematic trader.

Book is written by author having more than 10 years of experience. Co-


author of the book has worked with BSE Limited (formally known as
Bombay Stock Exchange) for 6 years from 2011 to 2017. Earlier to BSE he
worked with Broking houses like Edelweiss. Today he is a Option trader and
Arbitrager. He is also having more than 15 years of experience in Indian
Capital Market.
Books By This Author

THINK ARBITRAGE : Trading For Living


(This book will publish on 1st June 2021)

A comprehensive guide on Trading Strategies used by professional


traders/Arbitragers in Indian Capital Market. This book explain arbitrage
strategies with limited risk used by full time trader to earn consistent income
from trading.

Most of the trading strategies explained with historical per minute data Nifty
and Bank Nifty weekly options.

Book is written by author having more than 10 years of experience. Co-


author of the book has worked with BSE Limited (formally known as
Bombay Stock Exchange) for 6 years from 2011 to 2017. Earlier to BSE he
worked with broking houses like Edelweiss. Today he is a Option trader and
Arbitrager. He is also having more than 15 years of experience in Indian
Capital Market.

You might also like