In its simplest form, when the Supertrend is overlayed over a candlestick chart, if the Supertrend crosses to below the Price we take a Long Position and when the Supertrend crosses to above the Price, we take a Short position. Here is a snapshot of the Supertrend.
This article from Economic Times is probably a good place to start with to get a qucik overview of Supertrend.
So let us dive straight into and get the calculation of Supertrend. Check this Google Sheet for the Calculation of Supertrend.
Given below is the pseudo code for the calculation of Supertrend:
Basic UpperrBand = (High + Low) / 2 + Multiplier * ATR Basic LowerBand = (High + Low) / 2 - Multiplier * ATR Final UpperBand = IF((Current BasicUpperband < Previous Final UpperBand) OR (Previous Close > Previous Final UpperBand)) THEN (Current Basic UpperBand) ELSE (Previous FinalUpperBand) Final LowerBand = IF((Current Basic LowerBand > Previous Final LowerBand) OR (Previous Close < Previous Final LowerBand)) THEN (Current Basic LowerBand) ELSE (Previous Final LowerBand) SuperTrend = IF((Previous SuperTrend = Previous Final UpperBand) AND (Current Close <= Current Final UpperBand)) THEN Current Final UpperBand ELSE IF((Previous SuperTrend = Previous Final UpperBand) AND (Current Close > Current Final UpperBand)) THEN Current Final LowerBand ELSE IF((Previous SuperTrend = Previous Final LowerBand) AND (Current Close >= Current Final LowerBand)) THEN Current Final LowerBand ELSE IF((Previous SuperTrend = Previous Final LowerBand) AND (Current Close < Current Final LowerBand)) THEN Current Final UpperBand
Now lets see how this is calculated in Python. Lets first download the OHLCV data from the above google sheet into a CSV file. Name it as "test data". We can use this as our input file for the Python program.
Lets first take a look at the Imports and Global Declarations that we will use in this program:
#imports used in the program import numpy as np import pandas as pd #Global Declarations input_file = "test data.csv" multiplier = 2 # An integer to indicate the value to multiply the ATR. period = 14 atr = 'ATR' + '_' + str(period) st = 'SuperTrend' + '_' + str(period) + '_' + str(multiplier)
Since the Supertrend is based on Average True Range(ATR), lets define this function.
def AverageTrueRange(df_stock, period=14): """ Function to compute the technical indicator Average True Range(ATR) Args: df: Pandas DataFrame which contains ['Date', 'Open', 'High', 'Low', 'Close', 'Volume'] columns period: the period for which ATR has to be calculated, generally the number of candlesticks. Default is 14 Returns: df : Pandas DataFrame with two new columns 1) True Range (TR) 2) Average True Range (ATR_period) """ """ The True Range is calculated at the Higher of the following three: 1. Current High minus the current Low 2. Absolute Value of Current High minus the previous Close 3. Absolute Value of Current Low minus the previous Close """ atr = 'ATR' + '_' + str(period) df_stock['H-L'] = df_stock['High'] - df_stock['Low'] df_stock['PC'] = df_stock['Close'].shift(1) df_stock['H-PC'] = abs(df_stock['High'] - df_stock['PC']) df_stock['L-PC'] = abs(df_stock['Low'] - df_stock['PC']) df_stock['TR'] = df_stock[['H-L' ,'H-PC','L-PC']].max(axis=1) df_stock[atr] = np.nan # define a column ATR and initialise it with nan values df_stock.drop(['PC','H-PC','L-PC','H-L'], inplace=True, axis=1) # Drop the unwanted columns con = pd.concat([df_stock[:period]['TR'].rolling(window=period).mean(), df_stock[period:]['TR']]) df_stock[atr] = con.ewm(alpha=1 / period, adjust=False).mean() # print(df_stock[atr][period:len(df_stock)]) return df_stockNow lets get to the main program:
# Start of Main Program df_stock = pd.read_csv(input_file) df_stock = df_stock.reset_index(drop=True) # just reset the index without inserting it as a column in the DataFrame df_stock = AverageTrueRange(df_stock, 14)Next lets calculate the Basic Upper Bands and Lower Bands
# Calculate Basic Upperband and Basic Lowerbands df_stock['Basic_UB'] = (df_stock['High'] + df_stock['Low']) / 2 + multiplier*df_stock[atr] df_stock['Basic_LB'] = (df_stock['High'] + df_stock['Low']) / 2 - multiplier*df_stock[atr]Next lets calculate the final upperband and final lowerband
# Calculate Final upperband and Final lowerbands df_stock['Final_UB'] = 0.00 df_stock['Final_LB'] = 0.00 for i in range(period - 1, len(df_stock)): if (df_stock.loc[i, 'Basic_UB'] < df_stock.loc[i-1, 'Final_UB']) | (df_stock.loc[i-1, 'Close'] > df_stock.loc[i-1, 'Final_UB']): df_stock.loc[i,'Final_UB'] = df_stock.loc[i, 'Basic_UB'] else: df_stock.loc[i, 'Final_UB'] = df_stock.loc[i-1, 'Final_UB'] if (df_stock.loc[i, 'Basic_LB'] > df_stock.loc[i-1, 'Final_LB']) | (df_stock.loc[i-1, 'Close'] < df_stock.loc[i-1, 'Final_LB']): df_stock.loc[i, 'Final_LB'] = df_stock.loc[i, 'Basic_LB'] else: df_stock.loc[i, 'Final_LB'] = df_stock.loc[i-1, 'Final_LB']Next lets calculate the Supertrend
# Calculate the SuperTrend df_stock[st] = 0.00 i = 0 for i in range(period-1, len(df_stock)): if (df_stock.loc[i-1, st] == df_stock.loc[i-1, 'Final_UB']) & (df_stock.loc[i, 'Close'] <= df_stock.loc[i, 'Final_UB']): df_stock.loc[i, st] = df_stock.loc[i, 'Final_UB'] else: if (df_stock.loc[i-1, st] == df_stock.loc[i-1, 'Final_UB']) & (df_stock.loc[i, 'Close'] > df_stock.loc[i, 'Final_UB']): df_stock.loc[i, st] = df_stock.loc[i, 'Final_LB'] else: if (df_stock.loc[i-1, st] == df_stock.loc[i-1, 'Final_LB']) & (df_stock.loc[i, 'Close'] >= df_stock.loc[i, 'Final_LB']): df_stock.loc[i, st] = df_stock.loc[i, 'Final_LB'] else: if (df_stock.loc[i-1, st] == df_stock.loc[i-1, 'Final_LB']) & (df_stock.loc[i, 'Close'] < df_stock.loc[i, 'Final_LB']): df_stock.loc[i, st] = df_stock.loc[i, 'Final_UB']And finally some dressing
df_stock[st] = df_stock[st].replace(0, np.nan) # Replace the 0 with nan values df_stock.drop(['Basic_UB','Basic_LB','Final_UB','Final_LB'], inplace=True, axis=1) # Drop unnecessary columns
And this is the Output of the Supertrend calculated thus:
13 11150.678571 14 11119.719388 15 11094.901931 16 11043.392865 17 11043.392865 75 11796.310807 76 11796.310807 77 11796.310807 78 11796.310807 79 11796.310807 Name: SuperTrend_14_2, Length: 67, dtype: float64
And a good point to Note is that the Supertrend calculated thus tallies with the the value of Supertrend used in the charts of TradingView . For the Indian Traders, it means that it works well with Zerodha Kite and Fyers Web as well.
Note: A better approach is explored by user arkochhar in GitHub repo : https://github.com/arkochhar/Technical-Indicators/blob/master/indicator/indicators.py
No comments:
Post a Comment