Reputation: 133
I've been trying to replicate the Supertrend indicator in Python to match with "tradingview" supertrend - for a while now, but I'm hitting a wall. I've tried various approaches, including using libraries like ta-lib and custom implementations, but I just can't seem to get the exact behavior I'm looking for.
I'm wondering if anyone has experience with this and could offer some advice.
import yfinance as yf
import pandas as pd
import numpy as np
# 1. Get XRP-USD data
def get_crypto_data():
symbol = "XRP-USD"
data = yf.download(symbol, interval='5m', period='1mo')
return data
# 2. SuperTrend Calculation
def calculate_supertrend(df, period=10, multiplier=3.0, change_atr=True):
# Calculate ATR
high = df['High']
low = df['Low']
close = df['Close']
# Calculate True Range
tr1 = pd.DataFrame(high - low)
tr2 = pd.DataFrame(abs(high - close.shift(1)))
tr3 = pd.DataFrame(abs(low - close.shift(1)))
frames = [tr1, tr2, tr3]
tr = pd.concat(frames, axis=1, join='inner').max(axis=1)
# Calculate ATR
if change_atr:
atr = tr.ewm(alpha=1/period, min_periods=period).mean()
else:
atr = tr.rolling(window=period).mean()
# Calculate SuperTrend
hl2 = (high + low) / 2
# Basic bands
final_upperband = hl2 - (multiplier * atr)
final_lowerband = hl2 + (multiplier * atr)
# Initialize Supertrend columns
supertrend = pd.DataFrame(index=df.index)
supertrend['up'] = final_upperband
supertrend['down'] = final_lowerband
supertrend['trend'] = 1
# Calculate SuperTrend
for i in range(1, len(df.index)):
curr = df.index[i]
prev = df.index[i-1]
# Up trend
if close[curr] > supertrend.loc[prev, 'up']:
supertrend.loc[curr, 'up'] = max(supertrend.loc[prev, 'up'], final_upperband[curr])
else:
supertrend.loc[curr, 'up'] = final_upperband[curr]
# Down trend
if close[curr] < supertrend.loc[prev, 'down']:
supertrend.loc[curr, 'down'] = min(supertrend.loc[prev, 'down'], final_lowerband[curr])
else:
supertrend.loc[curr, 'down'] = final_lowerband[curr]
# Trend
if close[curr] > supertrend.loc[prev, 'down']:
supertrend.loc[curr, 'trend'] = 1
elif close[curr] < supertrend.loc[prev, 'up']:
supertrend.loc[curr, 'trend'] = -1
else:
supertrend.loc[curr, 'trend'] = supertrend.loc[prev, 'trend']
# Generate signals
supertrend['buy_signal'] = (supertrend['trend'] == 1) & (supertrend['trend'].shift(1) == -1)
supertrend['sell_signal'] = (supertrend['trend'] == -1) & (supertrend['trend'].shift(1) == 1)
return supertrend
# Main execution
def main():
# Get data
df = get_crypto_data()
# Calculate SuperTrend
st = calculate_supertrend(
df,
period=10, # ATR Period
multiplier=3.0, # ATR Multiplier
change_atr=True # Use EMA for ATR calculation
)
# Merge with original data
df['SuperTrend_Up'] = np.where(st['trend'] == 1, st['up'], np.nan)
df['SuperTrend_Down'] = np.where(st['trend'] == -1, st['down'], np.nan)
df['Trend'] = st['trend']
df['Buy_Signal'] = st['buy_signal']
df['Sell_Signal'] = st['sell_signal']
return df
if __name__ == "__main__":
result = main()
print(result.tail())
Upvotes: 0
Views: 136