Algo Trading
Avoid Bad Trade Entry with this Python Indicator!

FabTrader
Support and resistance levels are crucial for traders as they help identify key price zones where reversals or continuations are likely to occur. The Dynamic Support and Resistance indicator, originally developed by LonesomeTheBlue in Pine Script on TradingView, automates the process of detecting these levels. This indicator is one of the most used and most loved indicator by Traders. This indicator gets its following due to its simplicity and accuracy!
In this article, I will explain how I converted this TradingView indicator into Python and how it can be used to enhance automated trading strategies.
How the Original Indicator Works
The Dynamic Support and Resistance indicator operates using Pivot Points to create price channels. The core functionality is as follows:
- Finding Pivot Points: The indicator identifies pivot highs and pivot lows based on recent price action.
- Creating Channels: Each pivot point forms a channel. The channel size is determined using the formula:
- Counting Pivot Points in Each Channel: The number of pivot points within each channel is counted. Channels with more pivot points are considered stronger support or resistance levels.
- Filtering Strong Levels: A threshold for Support/Resistance strength (S/R Strength) is applied. A channel must have at least this many pivot points to qualify as a valid support or resistance level.
- Priority to Recent Pivot Points: The indicator prioritizes recent pivot points, as they are more relevant in current market conditions.
- Plotting Support and Resistance Lines: Once the support and resistance zones are identified, the indicator visually represents them as horizontal lines.
The default loopback period is 300 candles, ensuring that recent pivot points are given priority over older ones.
Why This Indicator is Useful
Many traders face the problem of unknowingly placing trades too close to major support or resistance levels. This can lead to:
- Entering a long trade near resistance, only to see price reverse and hit stop loss.
- Entering a short trade near support, resulting in a price bounce and a stop-out.
Using this indicator in trading strategies helps avoid such situations by providing clear key support and resistance zones.
Converting the Indicator to Python
I converted this TradingView indicator into Python so that it can be integrated into automated trading strategies. Below is its python implementation:
"""
------------------------------------------------------------------------------------
FabTrader Algo Trading
------------------------------------------------------------------------------------
This is the python version of the Dynamic Support and Resistance Indicator
in TradingView (by LonesomeTheBlue)
Copyright (c) 2024 FabTrader
LICENSE: PROPRIETARY SOFTWARE
- This software is the exclusive property of FabTrader.
- Unauthorized distribution, or commercial use is prohibited.
CONTACT:
- Website: https://fabtrader.in
- Email: [email protected]
Input:
1. Symbol
2. Timeframe
Output
1. Dynamic Support and Resistance levels
-- Dependencies to be installed --
pip install numpy
pip install pandas
Disclaimer:
The information provided is for educational and informational purposes only and
should not be construed as financial, investment, or legal advice. The content is based on publicly available
information and personal opinions and may not be suitable for all investors. Investing involves risks,
including the loss of principal.
"""
import pandas as pd
import numpy as np
import BrokerConnector
from Symbol_master import Instruments
from datetime import date, timedelta
def getDynamicSRLevels(symbol, timeframe):
def pivothigh(n, left_period, right_period):
ishigh = True
if n < left_period + right_period + 1:
ishigh = False
else:
musthighest = dfLB['High'][n - right_period]
for bar_index in range(n - left_period - right_period, n + 1):
if (dfLB['High'][bar_index] >= musthighest and bar_index != n - right_period):
ishigh = False
if (ishigh):
return musthighest
return None
def pivotlow(n, left_period, right_period):
islow = True
if n < left_period + right_period + 1:
islow = False
else:
mustlowest = dfLB['Low'][n - right_period]
for bar_index in range(n - left_period - right_period, n + 1):
if (dfLB['Low'][bar_index] <= mustlowest and bar_index != n - right_period):
islow = False
if (islow):
return mustlowest
return None
def highest(n, back):
value = None
for bar_index in range(n - back + 1, n + 1):
if bar_index < 0:
continue
if value is None or dfLB['High'][bar_index] > value:
value = dfLB['High'][bar_index]
return value
def lowest(n, back):
value = None
for bar_index in range(n - back + 1, n + 1):
if bar_index < 0:
continue
if value is None or dfLB['Low'][bar_index] < value:
value = dfLB['Low'][bar_index]
return value
# return value
def prev_value(col, n, back):
value = 0
if n < back + 1:
value = 0
else:
value = value = dfLB[col][n - back]
return value
# Initialize
rb = 10 # "Period for Pivot Points"
prd = 284 # "Loopback Period"
nump = 2 # "S/R strength"
ChannelW = 10 # "Channel Width %"
finalList = []
offset = 365
pd.options.mode.chained_assignment = None # default='warn'
# Extract historic data
if timeframe == 'day':
offset = 364
elif timeframe == '5':
offset = 4
elif timeframe == '15':
offset = 16
elif timeframe == '60':
offset = 55
else:
print('Not a valid timeframe')
offset = 4
begin = date.today() - timedelta(days=offset)
end = date.today()
#---------- Replace this code below with your own code to fetch historic data-----#
dfLB = Instruments.get_historical_data(symbol, begin, end, timeframe)
#---------- Replace this code below with your own code to fetch historic data-----#
dfLB = dfLB.tail(284)
dfLB.reset_index(inplace=True)
dfLB.columns = ['Date', 'Open', 'High', 'Low', 'Close', 'Volume']
if not dfLB.empty:
dfLB["ph"] = None
dfLB["pl"] = None
dfLB["u1"] = 0.0
dfLB["d1"] = 0.0
dfLB["highestph"] = 0.0
dfLB["lowestpl"] = 0.0
sr_levels = [None] * 21
totallen = len(dfLB.index)
prdlowest = 0
prdhighest = 0
for n, row in dfLB.iterrows():
ph = pivothigh(n, rb, rb)
pl = pivotlow(n, rb, rb)
dfLB.iloc[n, dfLB.columns.get_loc('ph')] = ph
dfLB.iloc[n, dfLB.columns.get_loc('pl')] = pl
prdhighest = highest(n, prd)
prdlowest = lowest(n, prd)
cwidth = (prdhighest - prdlowest) * ChannelW / 100
dfLB.iloc[n, dfLB.columns.get_loc("u1")] = prev_value("u1", n, 1)
dfLB.iloc[n, dfLB.columns.get_loc("d1")] = prev_value("d1", n, 1)
dfLB.iloc[n, dfLB.columns.get_loc("highestph")] = prev_value("highestph", n, 1)
dfLB.iloc[n, dfLB.columns.get_loc("lowestpl")] = prev_value("lowestpl", n, 1)
if ph is not None or pl is not None:
for x in range(len(sr_levels)):
sr_levels[x] = None
aas = [True] * 41
dfLB.iloc[n, dfLB.columns.get_loc("highestph")] = prdlowest
dfLB.iloc[n, dfLB.columns.get_loc("lowestpl")] = prdhighest
countpp = 0 # // keep position of the PP
for x in range(0, prd + 1):
if n < x + rb:
break
if dfLB["ph"][n - x] is not None or dfLB["pl"][n - x] is not None:
countpp = countpp + 1
if countpp > 40:
break
if aas[countpp]: # array.get(aas, countpp) // if PP is not used in a channel
upl = (dfLB['High'][n - x - rb] if dfLB["ph"][n - x] is not None else dfLB['Low'][
n - (x + rb)]) + cwidth
dnl = (dfLB['High'][n - x - rb] if dfLB["ph"][n - x] is not None else dfLB['Low'][
n - (x + rb)]) - cwidth
tmp = [True] * 41
cnt = 0
tpoint = 0
for xx in range(0, prd + 1):
if n < xx + rb:
break
if dfLB["ph"][n - xx] is not None or dfLB["pl"][n - xx] is not None:
chg = False
cnt = cnt + 1
if cnt > 40:
break
if aas[cnt]: # // if PP not used in other channels
if dfLB["ph"][n - xx] is not None: # not na(ph[xx])
if dfLB['High'][n - xx - rb] <= upl and dfLB['High'][
n - xx - rb] >= dnl: # // PP is in the channel?
tpoint = tpoint + 1
chg = True
if dfLB["pl"][n - xx] is not None:
if dfLB['Low'][n - xx - rb] <= upl and dfLB['Low'][
n - xx - rb] >= dnl: # // PP is in the channel?
tpoint = tpoint + 1
chg = True
if chg and cnt < 41:
tmp[cnt] = False
if tpoint >= nump: # // met enough PP in the channel? mark the PP as used for a channel and set the SR level
for g in range(41):
if not tmp[g]:
aas[g] = False
if dfLB["ph"][n - x] is not None and countpp < 21:
sr_levels[countpp] = dfLB['High'][n - x - rb]
if dfLB["pl"][n - x] is not None and countpp < 21:
sr_levels[countpp] = dfLB['Low'][n - x - rb]
finalList = sr_levels
finalList.append(prdlowest)
finalList.append(prdhighest)
finalList = [item for item in sr_levels if item is not None]
finalList = np.unique(finalList).tolist()
finalList.sort()
return finalList
else:
print("No data Supplied. Quitting")
return finalList
if __name__ == "__main__":
# Generate Dynamic Support and Resistance
symbol = "INFY"
timeframe = 'day' # Valid timeframes day, 5minute, 15minute, 60minute
print("Symbol :", symbol)
print("Dynamic Support and Resistance Levels:")
print(getDynamicSRLevels(symbol, "day"))


Application in Algorithmic Trading
This Python implementation can be integrated into automated trading strategies to enhance decision-making.
How it Helps in Algo Trading
- Avoiding bad trade entries: Ensures that no buy trades are placed near resistance and no sell trades near support.
- Optimizing stop-loss levels: Traders can use support levels for setting stop-loss orders in long trades and resistance levels for short trades.
- Dynamic adjustments: Unlike static support/resistance levels, this indicator adapts to recent price action, making it more relevant.
Conclusion
By converting the Dynamic Support and Resistance indicator from Pine Script to Python, we unlock new possibilities for automated trading strategies. This approach ensures traders avoid common pitfalls of placing trades too close to significant price zones, leading to better trade execution and risk management.
If you are building an algo trading system, integrating this Python-based support and resistance detection can help you make data-driven trading decisions.
More from Algo Trading
Algo Trading Cost in India: How I Built a Reliable Setup for ₹150/Month
Wondering how much algo trading costs in India? In this article, I break down the real expenses involved in running an algorithmic...
When Your Job Feels Shaky: Can Trading Become an Alternate Income Stream?
Can trading become a stable source of income in India? While many consider it during times of job uncertainty, the reality is...
How Much Capital Do You Really Need for Sustainable Trading Income in India?
How much capital is needed for sustainable trading income in India? This in-depth guide explores the realistic returns traders can expect, the...
