text: Title: TD Sequential + Charting 
  Body: **Which version are you running? The lastest version is on Github. Pip is for major releases.**
  0.2.23b0
  
  **Is your feature request related to a problem? Please describe.**
  The TD Sequential is a very popular indicator yet there are not many libraries available for it in Python. 
  Existing libraries such as in JavaScript are very bulky and do not scale very well. 
  The essence of TD Sequential is chart analysis and so we really need a way to embed the sequences on the chart above the candles. 
  
  **Describe the solution you'd like**
  A Pandas TD Sequential indicator that addresses issues of scalability. (e.g. capable of creating a TD Sequential column for a dataset of 1 million samples). 
  
  **Describe alternatives you've considered**
  There are TD Sequential indicators on TradingView however I would like one in Python. 
  
  **Additional context**
  I've created a Python TD Sequential that you may be able to work off. 
  I originally ported a JavaScript implementation but then added a simpler TD Sequential that could scale much better. 
  I've also heavily commented my simple implementation TDSequentialSimples() and added a Toy Dataset. 
  
  ```python
  #! /usr/bin/env python
  
  import argparse
  import os
  import sys
  import logging
  import pandas
  
  """
  TD Sequential
  A Python3 implementation of DeMark's TD Sequential. 
  Input: Pandas DataFrame with 'high','low','open','close' header 
  Output: detailed DataFrame of Sequential.
  Originally ported from JavaScript code.
  
  Toy Dataset example:
  python3 TDSequential.py
  
  Add function to create sequences of sequentials:
  shift = pandas.DataFrame(
          [td.shift(-x).transpose().values.tolist()[0] for x in range(1,context.SEQWINDOW + 1)]).transpose().dropna().values.tolist()
  """
  
  root = logging.getLogger()
  root.setLevel(logging.INFO)
  
  #TODO Add function to convert table of sequences to list of sequences k numbers long.
  
  class TDSequential(object):
          """
          Object class
          """
          def __init__(self):
                  self.resetSetupCounterAfterCountdownHit13 = True
                  self.resetCountdownOnTDST = True
  
          def TDSequentialSimples(self,ohlc):
                  '''Efficient Sequential Programmed by Troy.'''
                  # Return empty list if data is too small
                  if len(ohlc.values.tolist()) < 1: return []
                  # Convert all column labels to lower case
                  ohlc.columns = [x.lower() for x in ohlc.columns]
                  # Create buy and sell columns to count sequentials
                  ohlc['buy'] = ohlc['close'] * 0 ; ohlc['sell'] = ohlc['close'] * 0
                  # Convert buy and sell columns to int to save memory
                  ohlc.buy = ohlc.buy.astype(int) ; ohlc.sell = ohlc.sell.astype(int)
                  #Loop over ohlc data with reference to position (i)
                  for i, item in ohlc.iterrows():
                          # Only analyse data if there is enough trailing data
                          # (sequential looks back 4 and 5 canldes)
                          if i >= 5:
                                  # Core part of sequential : < or > 4 bars earlier
                                  closeLessThanCloseOf4BarsEarlier = ohlc.loc[i,'close'] < ohlc.loc[i-4,'close']
                                  closeGreaterThanCloseOf4BarsEarlier = ohlc.loc[i,'close'] > ohlc.loc[i-4,'close']
  
                                  # Logic for sequential : last 2 bars < or > 4 bars earlier
                                  bear = ohlc.loc[i-1,'close'] > ohlc.loc[i-5,'close'] and closeLessThanCloseOf4BarsEarlier
                                  bull = ohlc.loc[i-1,'close'] < ohlc.loc[i-5,'close'] and closeGreaterThanCloseOf4BarsEarlier
  
                                  # Seuquential can either be last 2 bar pattern OR 4 bars earlier + current green count
                                  if bear or (ohlc.loc[i-1,'buy'] > 0 and closeLessThanCloseOf4BarsEarlier):
                                          # Add number to buy counter
                                          ohlc.loc[i,'buy'] = (ohlc.loc[i-1,'buy']+1-1) % 9 + 1
                                  # Same logic for red counter
                                  elif bull or (ohlc.loc[i-1,'sell'] > 0 and closeGreaterThanCloseOf4BarsEarlier):
                                          # Minus number from sell counter
                                          ohlc.loc[i,'sell'] = (ohlc.loc[i-1,'sell']+1-1)%9+1
                  # Combine sell and buy columns into one sequential column
                  ohlc['sequential'] = (ohlc['buy']*-1) + (ohlc['sell']*1)
                  # convert output to integer instead of double
                  ohlc.sequential = ohlc.sequential.astype(int)
                  # Function is ammending ohlc without need for return (pass by value)
                  return ohlc['sequential']
  
          def TDSequential(self,ohlc,simple=False):
                  if len(ohlc.values.tolist()) < 1: return []
                  result = []
                  ohlc.columns = [x.lower() for x in ohlc.columns]
                  for i, item in ohlc.iterrows():
                          resultObj = self.getResultObj()
                          if i >= 5:
                                  resultObj['sellCoundownIndex'] = result[i - 1]['sellCoundownIndex']
                                  resultObj['buyCoundownIndex'] = result[i - 1]['buyCoundownIndex']
                                  resultObj['sellSetup'] = result[i - 1]['sellSetup']
                                  resultObj['buySetup'] = result[i-1]['buySetup']
                                  resultObj['TDSTBuy'] = result[i-1]['TDSTBuy']
                                  resultObj['TDSTSell'] = result[i-1]['TDSTSell']
                                  resultObj['sellSetupPerfection'] = result[i-1]['sellSetupPerfection']
                                  resultObj['buySetupPerfection'] = result[i-1]['buySetupPerfection']
                                  closeLessThanCloseOf4BarsEarlier = ohlc.loc[i,'close'] < ohlc.loc[i-4,'close']
                                  closeGreaterThanCloseOf4BarsEarlier = ohlc.loc[i,'close'] > ohlc.loc[i-4,'close']
  
                                  resultObj['bearishFlip'] = ohlc.loc[i-1,'close'] > ohlc.loc[i-5,'close'] and closeLessThanCloseOf4BarsEarlier
                                  resultObj['bullishFlip'] = ohlc.loc[i-1,'close'] < ohlc.loc[i-5,'close'] and closeGreaterThanCloseOf4BarsEarlier
  
                                  #NOTE bearishflip / bullishflip
                                  if resultObj['bearishFlip'] or (result[i-1]['buySetupIndex'] > 0 and closeLessThanCloseOf4BarsEarlier):
                                          resultObj['buySetupIndex'] = (result[i-1]['buySetupIndex']+1-1) % 9 + 1
                                          resultObj['TDSTBuy'] = max(ohlc.loc[i,'high'], result[i-1]['TDSTBuy'])
                                  elif resultObj['bullishFlip'] or (result[i-1]['sellSetupIndex'] > 0 and closeGreaterThanCloseOf4BarsEarlier):
                                          resultObj['sellSetupIndex'] = (result[i-1]['sellSetupIndex']+1-1)%9+1
                                          resultObj['TDSTSell'] = min(ohlc.loc[i,'low'], result[i-1]['TDSTSell'])
  
                                  if resultObj['buySetupIndex'] == 9:
                                          resultObj['buySetup'] = True
                                          resultObj['sellSetup'] = False
                                          resultObj['sellSetupPerfection'] = False
  
                                          resultObj['buySetupPerfection'] = (ohlc.loc[i-1,'low'] < ohlc.loc[i-3,'low'] and ohlc.loc[i-1,'low'] < ohlc.loc[i-2,'low']) or (ohlc.loc[i,'low'] < ohlc.loc[i-3,'low'] and ohlc.loc[i,'low'] < ohlc.loc[i-2,'low'])
  
  
  
                                  if resultObj['sellSetupIndex'] == 9:
                                          resultObj['sellSetup'] = True
                                          resultObj['buySetup'] = False
                                          resultObj['buySetupPerfection'] = False
                                          resultObj['sellSetupPerfection'] = (ohlc.loc[i-1,'high'] > ohlc.loc[i-3,'high'] and ohlc.loc[i-1,'high'] > ohlc.loc[i-2,'high']) or (ohlc.loc[i,'high'] > ohlc.loc[i-3,'high'] and ohlc.loc[i,'high'] > ohlc.loc[i-2,'high'])
  
  
  
                                  resultObj = self.calculateTDBuyCountdown(result,resultObj,ohlc,item,i)
                                  resultObj = self.calculateTDSellCountdown(result,resultObj,ohlc,item,i)
                          result+=[resultObj]
  
                  # if you run this seq with simple=True you get a single column output...
                  if simple:
                          #Return a simple version of the indicator...
  
                          #buySetupIndex,sellSetupIndex -> main sequential items
                          result2 = pandas.DataFrame()
                          #Had to convert dictionary format to pandas before calculating sequential
                          result = pandas.DataFrame(result)
                          #converted sell sequences to negative values and combined sell/buy sequences...
                          result2['sequential'] = (result['buySetupIndex']*-1)+(result['sellSetupIndex']*1)
                          result = result2
                  return result
  
  
          #TODO maybe create an alt version of this with just a list...
          def getResultObj(self):
                  resultObj ={
                          'buySetupIndex':0,
                          'sellSetupIndex':0,
                          'buyCoundownIndex':0,
                          'sellCoundownIndex':0,
                          'countdownIndexIsEqualToPreviousElement':True,
                          'sellSetup':False,
                          'buySetup':False,
                          'sellSetupPerfection':False,
                          'buySetupPerfection':False,
                          'bearishFlip':False,
                          'bullishFlip':False,
                          'TDSTBuy':0,
                          'TDSTSell':0,
                          'countdownResetForTDST':False}
                  return resultObj
  
          def calculateTDSellCountdown(self,result,resultObj,ohlc,item,i):
                  #TODO used item['TDSTSell'] but item is ohcl??
                  if (result[i-1]['sellSetup'] and resultObj['buySetup']) or (self.resetCountdownOnTDST and ohlc.loc[i,'close']<resultObj['TDSTSell']):
                          resultObj['sellCoundownIndex']=0
                          resultObj['countdownResetForTDST']=True
                  elif resultObj['sellSetup']:
                          if ohlc.loc[i,'close']>ohlc.loc[i-2,'high']:
                                  resultObj['sellCoundownIndex'] = (result[i-1]['sellCoundownIndex']+1-1)%13+1
                                  resultObj['countdownIndexIsEqualToPreviousElement'] = False
  
  
                  if resultObj['sellCoundownIndex']==13 and result[i-1]['sellCoundownIndex']==13:
                          resultObj['sellCoundownIndex']=0
  
  
                  if self.resetSetupCounterAfterCountdownHit13 and (resultObj['sellCoundownIndex']==13 and resultObj['sellSetupIndex']>0):
                          resultObj['sellSetupIndex']=1
  
  
  
                  if resultObj['sellCoundownIndex']!=13 and result[i-1]['sellCoundownIndex']==13:
                          resultObj['sellSetup']=False
                          resultObj['sellSetupPerfection']=False
                          resultObj['sellCoundownIndex']=0
                  return resultObj
  
  
  
          
          def calculateTDBuyCountdown(self,result,resultObj,ohlc,item,i):
                  if (result[i-1]['buySetup'] and resultObj['sellSetup']) or (self.resetCountdownOnTDST and ohlc.loc[i,'close']>resultObj['TDSTBuy']):
                          resultObj['buyCoundownIndex']=0
                          resultObj['countdownResetForTDST']=True
                  elif resultObj['buySetup']:
                          if ohlc.loc[i,'close']<ohlc.loc[i-2,'low']:
                                  resultObj['buyCoundownIndex'] = (result[i-1]['buyCoundownIndex']+1-1)%+1
                                  resultObj['countdownIndexIsEqualToPreviousElement']=False
  
  
                  
                  if resultObj['buyCoundownIndex']==13 and result[i-1]['buyCoundownIndex']==13:
                          resultObj['buyCoundownIndex']=0
  
  
                  if self.resetSetupCounterAfterCountdownHit13 and (resultObj['buyCoundownIndex']==13 and resultObj['buySetupIndex']>0):
                          resultObj['buySetupIndex']=1
  
  
                  if resultObj['buyCoundownIndex']!=13 and result[i-1]['buyCoundownIndex']==13:
                          resultObj['buySetup']=False
                          resultObj['buySetupPerfection']=False
                          resultObj['buyCoundownIndex']=0
                          
                  return resultObj
  
  """
  Main section
  """
  def main(args):
          logging.info('Testing TDSequentia Toy Dataset')
          td = TDSequential()
          
          data=[[3810.16,3701.23,3797.14,3642.0],
          [3882.14,3796.4500000000003,3858.56,3750.4500000000003],
          [3862.7400000000002,3857.57,3766.78,3730.0],
          [3823.64,3767.2000000000003,3792.01,3703.57],
          [3840.9900000000002,3790.09,3770.96,3751.0],
          [4027.71,3771.12,3987.6,3740.0],
          [4017.9,3987.62,3975.4500000000003,3921.53],
          [4069.8,3976.76,3955.13,3903.0],
          [4006.81,3955.4500000000003,3966.65,3930.04],
          [3996.01,3966.06,3585.88,3540.0],
          [3658.0,3585.88,3601.31,3465.0],
          [3618.19,3601.31,3583.13,3530.0],
          [3611.1,3584.1,3476.81,3441.3],
          [3671.87,3477.56,3626.09,3467.02],
          [3648.42,3626.08,3553.06,3516.62],
          [3645.0,3553.06,3591.84,3543.51],
          [3634.7000000000003,3591.84,3616.21,3530.39],
          [3620.0,3613.32,3594.87,3565.75],
          [3720.0,3594.87,3665.3,3594.23],
          [3693.73,3665.75,3539.28,3475.0],
          [3559.51,3539.26,3526.9,3475.5],
          [3608.5,3526.88,3570.9300000000003,3434.85],
          [3607.98,3570.41,3552.82,3514.5]]
          
          #ohcl = pandas.read_csv('outputcsv.csv')
          ohcl = pandas.DataFrame(data)
          #NOTE mixed case will work... High/high works fine....
          ohcl.columns = ['High','open','Close','low']
          print(ohcl)
          #sys.exit()
          #x = pandas.DataFrame(td.TDSequential(ohcl,simple=True))
          x = pandas.DataFrame(td.TDSequentialSimples(ohcl))
          print(x.values.tolist())
          print(x.columns.tolist())
          #y = pandas.concat([ohcl,x],axis=1)
          print(ohcl)
          
  if __name__ == '__main__':     
          """
          Argparse section
          """
          parser = argparse.ArgumentParser(description=__doc__)
          #parser.add_argument('input', help='Text file in raw format. ')
          #parser.add_argument('output', help='File to output list of sentences. ')
          #parser.add_argument('-n',
          #                help='Minimum number of chars (default 5)',
          #                type=int, default=5, dest='minlength')
  
          args = parser.parse_args()
  
          main(args)
  ```