Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SuperTrend code using pandas python

I am trying to code the following algorithm for SuperTrend indicator in python using pandas.

BASIC UPPERBAND = (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

Here is the code that I wrote and tested:

# Compute basic upper and lower bands
df['basic_ub'] = (df['high'] + df['low']) / 2 + multiplier * df[atr]
df['basic_lb'] = (df['high'] + df['low']) / 2 - multiplier * df[atr]

# Compute final upper and lower bands
for i in range(0, len(df)):
    if i < period:
        df.set_value(i, 'basic_ub', 0.00)
        df.set_value(i, 'basic_lb', 0.00)
        df.set_value(i, 'final_ub', 0.00)
        df.set_value(i, 'final_lb', 0.00)
    else:
        df.set_value(i, 'final_ub', (df.get_value(i, 'basic_ub') 
                                     if df.get_value(i, 'basic_ub') < df.get_value(i-1, 'final_ub') or df.get_value(i-1, 'close') > df.get_value(i-1, 'final_ub') 
                                     else df.get_value(i-1, 'final_ub')))
        df.set_value(i, 'final_lb', (df.get_value(i, 'basic_lb') 
                                     if df.get_value(i, 'basic_lb') > df.get_value(i-1, 'final_lb') or df.get_value(i-1, 'close') < df.get_value(i-1, 'final_lb') 
                                     else df.get_value(i-1, 'final_lb')))

# Set the Supertrend value
for i in range(0, len(df)):
    if i < period:
        df.set_value(i, st, 0.00)
    else:
        df.set_value(i, 'st', (df.get_value(i, 'final_ub')
                             if ((df.get_value(i-1, 'st') == df.get_value(i-1, 'final_ub')) and (df.get_value(i, 'close') <= df.get_value(i, 'final_ub')))
                             else (df.get_value(i, 'final_lb')
                                   if ((df.get_value(i-1, 'st') == df.get_value(i-1, 'final_ub')) and (df.get_value(i, 'close') > df.get_value(i, 'final_ub')))
                                   else (df.get_value(i, 'final_lb')
                                         if ((df.get_value(i-1, 'st') == df.get_value(i-1, 'final_lb')) and (df.get_value(i, 'close') >= df.get_value(i, 'final_lb')))
                                         else (df.get_value(i, 'final_ub')
                                               if((df.get_value(i-1, 'st') == df.get_value(i-1, 'final_lb')) and (df.get_value(i, 'close') < df.get_value(i, 'final_lb')))
                                               else 0.00
                                              )
                                        )
                                  ) 
                            )
                    )


# Mark the trend direction up/down
df['stx'] = np.where((df['st'] > 0.00), np.where((df['close'] < df['st']), 'down',  'up'), np.NaN)

I works, but I am not happy with the for loop. Can anyone help optimise it?

You can find the released code on Github!

like image 589
arkochhar Avatar asked Sep 07 '25 00:09

arkochhar


1 Answers

SuperTrend Indicator is included in pandas_ta where you can simply:

import pandas_ta as ta

sti = ta.supertrend(df['High'], df['Low'], df['Close'], length=7, multiplier=3)

Given that df is a pandas DataFrame with OHLC prices, the result sti is a DataFrame with 4 columns:

  1. trend
  2. direction
  3. long
  4. short

where the trend is a concatenation of the long and short lines. Note that column captions are dynamic and contain the length and multiplier parameter values.

like image 120
mac13k Avatar answered Sep 08 '25 12:09

mac13k