code: def handleTrailingStops(self, tickerId):
          
  
          # existing?
          if tickerId not in self.trailingStops.keys():
              return None
  
          # continue
          trailingStop   = self.trailingStops[tickerId]
          price          = self.marketData[tickerId]['last'][0]
          symbol         = self.tickerSymbol(tickerId)
          # contract       = self.contracts[tickerId]
          # contractString = self.contractString(contract)
  
          # filled / no positions?
          if (self._positions[symbol] == 0) | \
                  (self.orders[trailingStop['orderId']]['status'] == "FILLED"):
              del self.trailingStops[tickerId]
              return None
  
          # continue...
          newStop  = trailingStop['lastPrice']
          ticksize = trailingStop['ticksize']
  
          # long
          if (trailingStop['quantity'] < 0) & (trailingStop['lastPrice'] < price):
              if abs(trailingStop['trailAmount']) >= 0:
                  newStop = price - abs(trailingStop['trailAmount'])
              elif trailingStop['trailPercent'] >= 0:
                  newStop = price - (price * (abs(trailingStop['trailPercent']) / 100))
          # short
          elif (trailingStop['quantity'] > 0) & (trailingStop['lastPrice'] > price):
              if abs(trailingStop['trailAmount']) >= 0:
                  newStop = price + abs(trailingStop['trailAmount'])
              elif trailingStop['trailPercent'] >= 0:
                  newStop = price + (price * (abs(trailingStop['trailPercent']) / 100))
  
          # valid newStop
          newStop = self.roundClosestValid(newStop, ticksize)
  
          # print("\n\n", trailingStop['lastPrice'], newStop, price, "\n\n")
  
          # no change?
          if newStop == trailingStop['lastPrice']:
              return None
  
          # submit order
          trailingStopOrderId = self.modifyStopOrder(
              orderId  = trailingStop['orderId'],
              parentId = trailingStop['parentId'],
              newStop  = newStop,
              quantity = trailingStop['quantity']
          )
  
          if trailingStopOrderId:
              self.trailingStops[tickerId]['lastPrice'] = price
  
          return trailingStopOrderId
docs: software-based trailing stop