code: # Add import from parent directory possible
  import matplotlib.pyplot as plt
  from helpers.DataOperations import FindIntersections, CreateSubsetByValues
  from core.indicator import indicator
  # Creates  object
  
  
  def CreateBollinger(prices, n=20, k=2):
      return Bollinger(prices, n, k)
  
  # Bollinger object which creates Bollinger data
  
  
  class Bollinger(indicator):
  
      def __init__(self, close, n=20, k=2):
          indicator.__init__(self, 'Bollinger', 'momentum', close.index)
          self.n = n
          self.k = k
          self.consolidationLvl = 15  # percent
          self.variabilityLvl = 50  # percent
          self.mavg, self.upperBand, self.lowerBand = self.InitBollinger(
              close, self.n, self.k)
          self.std = self.upperBand - self.lowerBand
          self.absStd = (self.std * 100) / self.std.max()
  
          # Signals
          fromBottom, fromTop = FindIntersections(self.upperBand, close)
          self.sell = fromBottom
          fromBottom, fromTop = FindIntersections(self.lowerBand, close)
          self.buy = fromTop
          self.consolidation = CreateSubsetByValues(
              self.absStd, 0, self.consolidationLvl)
          self.variability = CreateSubsetByValues(
              self.absStd, self.variabilityLvl, 100)
  
      # Set Bollinger indicator
      @staticmethod
      def InitBollinger(prices, n=20, k=2):
          mavg = prices.rolling(window=n, min_periods=1).mean()
          std = prices.rolling(window=n, min_periods=1).std()
          upperBand = mavg + (std * 2)
          lowerBand = mavg - (std * 2)
          return mavg, upperBand, lowerBand
  
      # Export indicator signals to report
      def ExportSignals(self, reportSignals):
          reportSignals.AddDataframeSignals(self.buy, 'Bollinger', 'buy')
          reportSignals.AddDataframeSignals(self.sell, 'Bollinger', 'sell')
  
      # Plot method
      def Plot(self):
          # Get index values for the X axis for facebook DataFrame
          x_axis = self.toNumIndex(self.upperBand)
  
          # Plot shaded 21 Day Bollinger Band for Facebook
          plt.fill_between(x_axis, self.upperBand,
                           self.lowerBand, color='#BBBBBB')
          plt.plot(self.toNumIndex(self.upperBand), self.upperBand, '--',
                   linewidth=1.0, color='#940006', label='Sell band')
          plt.plot(self.toNumIndex(self.lowerBand), self.lowerBand, '--',
                   linewidth=1.0, color='#169400', label='Buy band')
          plt.plot(self.toNumIndex(self.mavg), self.mavg, '--', linewidth=1.0,
                   color='#0000FF', label=('MA %s days' % self.n))
  
          # Signals plottting
          if (self.buy is not None and self.buy.size):
              plt.plot(self.toNumIndex(self.buy), self.buy,
                       'o', color='#000000', ms=8)
              plt.plot(self.toNumIndex(self.buy), self.buy, 'o',
                       label='Horiz. Buy', color='#00FF00')
          if (self.sell is not None and self.sell.size):
              plt.plot(self.toNumIndex(self.sell),
                       self.sell, 'o', color='#000000', ms=8)
              plt.plot(self.toNumIndex(self.sell), self.sell, 'o',
                       label='Horiz. Sell', color='#FF0000')
  
      # Plot method
      def PlotAbsDeviation(self):
          plt.plot(self.toNumIndex(self.absStd), self.absStd, linewidth=1.0,
                   color='#333333', label='Bol.AbsDeviation')
          plt.ylim(top=100, bottom=0)
          if (self.consolidation is not None and self.consolidation.size):
              plt.plot(self.toNumIndex(self.consolidation), self.consolidation,
                       'o', label='Consolidation', color='cyan')
          if (self.variability is not None and self.variability.size):
              plt.plot(self.toNumIndex(self.variability), self.variability,
                       'o', label='Variability', color='magenta')
  
apis: matplotlib.pyplot.fill_between matplotlib.pyplot.ylim