diff --git a/backtesting/_plotting.py b/backtesting/_plotting.py
index bec6757a..879e88b1 100644
--- a/backtesting/_plotting.py
+++ b/backtesting/_plotting.py
@@ -513,6 +513,7 @@ def __eq__(self, other):
 
             is_overlay = value._opts['overlay']
             is_scatter = value._opts['scatter']
+            is_histogram = value._opts['histogram']
             if is_overlay:
                 fig = fig_ohlc
             else:
@@ -523,6 +524,10 @@ def __eq__(self, other):
             colors = colors and cycle(_as_list(colors)) or (
                 cycle([next(ohlc_colors)]) if is_overlay else colorgen())
             legend_label = LegendStr(value.name)
+            indicator_max = value.df.max(axis='columns')
+            indicator_min = value.df.min(axis='columns')
+            source.add(indicator_max, f'indicator_{i}_range_max')
+            source.add(indicator_min, f'indicator_{i}_range_min')
             for j, arr in enumerate(value, 1):
                 color = next(colors)
                 source_name = f'{legend_label}_{i}_{j}'
@@ -532,7 +537,10 @@ def __eq__(self, other):
                 tooltips.append(f'@{{{source_name}}}{{0,0.0[0000]}}')
                 if is_overlay:
                     ohlc_extreme_values[source_name] = arr
-                    if is_scatter:
+                    if is_histogram:
+                        fig.vbar('index', BAR_WIDTH, source_name, source=source,
+                                 legend_label=legend_label, color=color)
+                    elif is_scatter:
                         fig.scatter(
                             'index', source_name, source=source,
                             legend_label=legend_label, color=color,
@@ -544,7 +552,10 @@ def __eq__(self, other):
                             legend_label=legend_label, line_color=color,
                             line_width=1.3)
                 else:
-                    if is_scatter:
+                    if is_histogram:
+                        r = fig.vbar('index', BAR_WIDTH, source_name, source=source,
+                                     legend_label=LegendStr(legend_label), color=color)
+                    elif is_scatter:
                         r = fig.scatter(
                             'index', source_name, source=source,
                             legend_label=LegendStr(legend_label), color=color,
@@ -584,7 +595,8 @@ def __eq__(self, other):
         figs_above_ohlc.append(_plot_drawdown_section())
 
     if plot_pl:
-        figs_above_ohlc.append(_plot_pl_section())
+        fig_pl = _plot_pl_section()
+        figs_above_ohlc.append(fig_pl)
 
     if plot_volume:
         fig_volume = _plot_volume_section()
@@ -607,9 +619,15 @@ def __eq__(self, other):
 
     custom_js_args = dict(ohlc_range=fig_ohlc.y_range,
                           source=source)
+    if plot_pl:
+        custom_js_args.update(pl_range=fig_pl.y_range)
     if plot_volume:
         custom_js_args.update(volume_range=fig_volume.y_range)
-
+    indicator_ranges = {}
+    for idx, indicator in enumerate(indicator_figs):
+        indicator_range_key = f'indicator_{idx}_range'
+        indicator_ranges.update({indicator_range_key: indicator.y_range})
+    custom_js_args.update({'indicator_ranges': indicator_ranges})
     fig_ohlc.x_range.js_on_change('end', CustomJS(args=custom_js_args,
                                                   code=_AUTOSCALE_JS_CALLBACK))
 
diff --git a/backtesting/autoscale_cb.js b/backtesting/autoscale_cb.js
index da888ecf..63135615 100644
--- a/backtesting/autoscale_cb.js
+++ b/backtesting/autoscale_cb.js
@@ -31,5 +31,18 @@ window._bt_autoscale_timeout = setTimeout(function () {
         max = Math.max.apply(null, source.data['Volume'].slice(i, j));
         _bt_scale_range(volume_range, 0, max * 1.03, false);
     }
+    
+    if(indicator_ranges){
+        let keys = Object.keys(indicator_ranges);
+        for(var count=0;count<keys.length;count++){
+            if(keys[count]){
+                max = Math.max.apply(null, source.data[keys[count]+'_max'].slice(i, j));
+                min = Math.min.apply(null, source.data[keys[count]+'_min'].slice(i, j));
+                if(min && max){
+                    _bt_scale_range(indicator_ranges[keys[count]], min, max, true);
+                }    
+            }
+        }
+    }
 
 }, 50);
diff --git a/backtesting/backtesting.py b/backtesting/backtesting.py
index edb7be01..41b7a7d5 100644
--- a/backtesting/backtesting.py
+++ b/backtesting/backtesting.py
@@ -75,7 +75,7 @@ def _check_params(self, params):
 
     def I(self,  # noqa: E741, E743
           func: Callable, *args,
-          name=None, plot=True, overlay=None, color=None, scatter=False,
+          name=None, plot=True, overlay=None, color=None, scatter=False, histogram=False,
           **kwargs) -> np.ndarray:
         """
         Declare indicator. An indicator is just an array of values,
@@ -105,6 +105,10 @@ def I(self,  # noqa: E741, E743
         If `scatter` is `True`, the plotted indicator marker will be a
         circle instead of a connected line segment (default).
 
+        If `histogram` is `True`, the indicator values will be plotted
+        as a histogram instead of line or circle. When `histogram` is
+        `True`, 'scatter' value will be ignored even if it's set.
+
         Additional `*args` and `**kwargs` are passed to `func` and can
         be used for parameters.
 
@@ -151,7 +155,7 @@ def init():
                 overlay = ((x < 1.4) & (x > .6)).mean() > .6
 
         value = _Indicator(value, name=name, plot=plot, overlay=overlay,
-                           color=color, scatter=scatter,
+                           color=color, scatter=scatter, histogram=histogram,
                            # _Indicator.s Series accessor uses this:
                            index=self.data.index)
         self._indicators.append(value)
diff --git a/backtesting/lib.py b/backtesting/lib.py
index f7f61e74..f7715e20 100644
--- a/backtesting/lib.py
+++ b/backtesting/lib.py
@@ -452,6 +452,43 @@ def next(self):
                                self.data.Close[index] + self.__atr[index] * self.__n_atr)
 
 
+class PercentageTrailingStrategy(Strategy):
+    """
+    A strategy with automatic trailing stop-loss, trailing the current
+    price at distance of some percentage. Call
+    `PercentageTrailingStrategy.set_trailing_sl()` to set said percentage
+    (`5` by default). See [tutorials] for usage examples.
+
+    [tutorials]: index.html#tutorials
+
+    Remember to call `super().init()` and `super().next()` in your
+    overridden methods.
+    """
+    _sl_percent = 5.
+
+    def init(self):
+        super().init()
+
+    def set_trailing_sl(self, percentage: float = 5):
+        assert percentage > 0, "percentage must be greater than 0"
+        """
+        Sets the future trailing stop-loss as some (`percentage`)
+        percentage away from the current price.
+        """
+        self._sl_percent = percentage
+
+    def next(self):
+        super().next()
+        index = len(self.data)-1
+        for trade in self.trades:
+            if trade.is_long:
+                trade.sl = max(trade.sl or -np.inf,
+                               self.data.Close[index]*(1-(self._sl_percent/100)))
+            else:
+                trade.sl = min(trade.sl or np.inf,
+                               self.data.Close[index]*(1+(self._sl_percent/100)))
+
+
 # Prevent pdoc3 documenting __init__ signature of Strategy subclasses
 for cls in list(globals().values()):
     if isinstance(cls, type) and issubclass(cls, Strategy):
diff --git a/backtesting/test/_test.py b/backtesting/test/_test.py
index 85ecea6a..0b0c1a51 100644
--- a/backtesting/test/_test.py
+++ b/backtesting/test/_test.py
@@ -24,6 +24,7 @@
     quantile,
     SignalStrategy,
     TrailingStrategy,
+    PercentageTrailingStrategy,
     resample_apply,
     plot_heatmaps,
     random_ohlc_data,
@@ -771,6 +772,24 @@ def next(self):
                     plot_drawdown=False, plot_equity=False, plot_pl=False, plot_volume=False,
                     open_browser=False)
 
+    def test_indicator_histogram(self):
+        class S(Strategy):
+            def init(self):
+                self.I(SMA, self.data.Close, 5, overlay=True, scatter=False, histogram=True)
+                self.I(SMA, self.data.Close, 10, overlay=False, scatter=False, histogram=True)
+
+            def next(self):
+                pass
+
+        bt = Backtest(GOOG, S)
+        bt.run()
+        with _tempfile() as f:
+            bt.plot(filename=f,
+                    plot_drawdown=False, plot_equity=False, plot_pl=False, plot_volume=False,
+                    open_browser=True)
+            # Give browser time to open before tempfile is removed
+            time.sleep(1)
+
 
 class TestLib(TestCase):
     def test_barssince(self):
@@ -862,6 +881,21 @@ def next(self):
         stats = Backtest(GOOG, S).run()
         self.assertEqual(stats['# Trades'], 57)
 
+    def test_PercentageTrailingStrategy(self):
+        class S(PercentageTrailingStrategy):
+            def init(self):
+                super().init()
+                self.set_trailing_sl(5)
+                self.sma = self.I(lambda: self.data.Close.s.rolling(10).mean())
+
+            def next(self):
+                super().next()
+                if not self.position and self.data.Close > self.sma:
+                    self.buy()
+
+        stats = Backtest(GOOG, S).run()
+        self.assertEqual(stats['# Trades'], 91)
+
 
 class TestUtil(TestCase):
     def test_as_str(self):