freakabhi
freakabhi

Reputation: 133

Need implementation of tradingView indicator "SuperTrend" indicator in python - I am not able to match 100%

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

Answers (0)

Related Questions