I’ve been trying to backtest a simple Supertrend strategy on 5 min Dhan data for INDORAMA, SOUTHBANK, INDOFARM on 20th Oct 2025, and I’m stuck with 0 trades despite the market being in a clear uptrend all day.
What I’m doing:
Fetching 5-min intraday data using:
{
“securityId”: “10993”,
“exchangeSegment”: “NSE_EQ”,
“instrument”: “EQUITY”,
“interval”: “5”,
“oi”: false,
“fromDate”: “2025-10-20 09:15:00”,
“toDate”: “2025-10-20 15:30:00”
}
- Getting 74 candles, timestamps in epoch seconds — all good.
- Using manual Supertrend logic (no pandas_ta) to match TradingView Pine v6.
- Buy condition:
- close > Supertrend
- Green candle (close > open)
- Previous direction was uptrend (direction[i-1] < 0)
Problem:
- No buys at all.
- But when I check the charts, all three stocks were above Supertrend from 09:15 onwards.
- Log shows data fetched, but no “BUY” entries.
- supertrend_trades.csv is empty.
Latest Log (last few lines):
2025-10-24 09:18:56,867 Fetched 74 5-min candles for 10993
2025-10-24 09:18:58,177 Fetched 74 5-min candles for 5948
2025-10-24 09:18:59,478 Fetched 74 5-min candles for 29025
My Questions:
- Is my manual Supertrend logic correct vs. TradingView?
- Why no buy signals even when close > Supertrend + green candle?
- Should the uptrend switch condition be removed for the first signal?
- Any known issues with 5min data alignment or ATR calculation in Python?
Here’s my code: import requests
import pandas as pd
import logging
import numpy as np
logging.basicConfig(level=logging.INFO)
— Dhan API —
def fetch_data(security_id):
url = “https://api.dhan.co/v2/charts/intraday”
payload = {
“securityId”: str(security_id),
“exchangeSegment”: “NSE_EQ”,
“instrument”: “EQUITY”,
“interval”: “5”,
“oi”: False,
“fromDate”: “2025-10-20 09:15:00”,
“toDate”: “2025-10-20 15:30:00”
}
headers = {
‘access-token’: ‘YOUR_TOKEN_HERE’,
‘client-id’: ‘YOUR_CLIENT_ID_HERE’,
‘Content-Type’: ‘application/json’
}
r = requests.post(url, json=payload, headers=headers)
d = r.json()
df = pd.DataFrame({
‘open’: d[‘open’], ‘high’: d[‘high’], ‘low’: d[‘low’],
‘close’: d[‘close’], ‘volume’: d[‘volume’]
})
df[‘timestamp’] = pd.to_datetime(d[‘timestamp’], unit=‘s’)
df.set_index(‘timestamp’, inplace=True)
logging.info(f"Fetched {len(df)} candles for {security_id}")
return df
— Manual Supertrend (Pine v6) —
def supertrend(df, length=10, mult=3.0):
tr1 = df[‘high’] - df[‘low’]
tr2 = (df[‘high’] - df[‘close’].shift(1)).abs()
tr3 = (df[‘low’] - df[‘close’].shift(1)).abs()
tr = pd.concat([tr1, tr2, tr3], axis=1).max(axis=1)
atr = tr.rolling(length).mean()
hl2 = (df[‘high’] + df[‘low’]) / 2
upper = hl2 + mult * atr
lower = hl2 - mult * atr
st = pd.Series(np.nan, index=df.index)
direction = pd.Series(np.nan, index=df.index)
for i in range(length, len(df)):
final_upper = upper.iloc[i] if df['close'].iloc[i-1] > upper.iloc[i-1] else min(upper.iloc[i], upper.iloc[i-1])
final_lower = lower.iloc[i] if df['close'].iloc[i-1] < lower.iloc[i-1] else max(lower.iloc[i], lower.iloc[i-1])
if df['close'].iloc[i] > final_upper:
st.iloc[i] = final_lower
elif df['close'].iloc[i] < final_lower:
st.iloc[i] = final_upper
else:
st.iloc[i] = st.iloc[i-1]
direction.iloc[i] = 1 if st.iloc[i] > st.iloc[i-1] else -1
return st, direction
— Backtest —
def run(symbol, sid):
df = fetch_data(sid)
st, dir = supertrend(df)
df = df.assign(Supertrend=st, Direction=dir)
pos = None
for i in range(1, len(df)):
c = df.iloc[i]
t = c.name
green = c['close'] > c['open']
above = c['close'] > st.iloc[i]
up = dir.iloc[i-1] < 0
if not pos and green and above and up:
entry = c['close'] * 1.001
qty = np.floor(50000 / entry)
if qty > 0:
pos = {'entry': entry, 'qty': qty, 'time': t}
logging.info(f"BUY {symbol} @ {t} price={entry:.2f}")
if pos and (dir.iloc[i] > 0 or t.hour >= 15):
exit_p = c['close'] * 0.999
pnl = (exit_p - pos['entry']) * pos['qty']
logging.info(f"SELL {symbol} @ {t} pnl={pnl:.2f}")
pos = None
— Run —
run(“INDORAMA”, 10993)
run(“SOUTHBANK”, 5948)
run(“INDOFARM”, 29025)
@Hardik @Shubham_Singh @Trishul_Devadiga @Shrutika_Poojari @Prithvi