book
Checkout our new book! Hands on AI Trading with Python, QuantConnect, and AWS Learn More arrow

Renko Consolidators

Classic Renko Consolidators

Introduction

Most Renko consolidators aggregate bars based on a fixed price movement. The ClassicRenkoConsolidator produces a different type of Renko bars than the RenkoConsolidator. A ClassicRenkoConsolidator with a bar size of $1 produces a new bar that spans $1 every time an asset closes $1 away from the close of the previous bar. If the price jumps multiple dollars in a single tick, the ClassicRenkoConsolidator only produces one bar per time step where the open of each bar matches the close of the previous bar.

Consolidate Trade Bars

TradeBar consolidators aggregate TradeBar objects into RenkoBar objects. Follow these steps to create and manage a TradeBar consolidator based on the preceding Renko bar rules:

  1. Create the consolidator.
  2. To create a classic Renko consolidator, pass the bar size to the ClassicRenkoConsolidator constructor.

    // Create a Classic Renko consolidator that emits a bar when the price moves $1
    _consolidator = new ClassicRenkoConsolidator(1m);
    # Create a Classic Renko consolidator that emits a bar when the price moves $1
    self._consolidator = ClassicRenkoConsolidator(1)

    The ClassicRenkoConsolidator has the following default behavior:

    • It uses the Valuevalue property of the IBaseData object it receives to build the Renko bars
    • It ignores the volume of the input data
    • It enforces the open and close of each bar to be a multiple of the bar size

    To build the Renko bars with a different property than the Valuevalue of the IBaseData object, provide a selector argument. The selector should be a function that receives the IBaseData object and returns a decimal value.

    self._consolidator = ClassicRenkoConsolidator(1, selector = lambda data: data.high)
    _consolidator = new ClassicRenkoConsolidator(1m, data => (data as TradeBar).High);

    To add a non-zero Volumevolume property to the Renko bars, provide a volumeSelectorvolume_selector argument. The volumeSelectorvolume_selector should be a function that receives the IBaseData object and returns a decimal value.

    self._consolidator = ClassicRenkoConsolidator(1, volume_selector = lambda data: data.volume)
    _consolidator = new ClassicRenkoConsolidator(1m, null, data => (data as TradeBar).Volume);

    To relax the requirement that the open and close of the Renko bars must be a multiple of bar size, disable the evenBarseven_bars argument. If you disable evenBarseven_bars, the open value of the first Renko bar is set to the first value from the selector. The following opening and closing Renko bar values are all multiples of the first value from the selector

    self._consolidator = ClassicRenkoConsolidator(1, even_bars=False)
    _consolidator = new ClassicRenkoConsolidator(1m, evenBars: false);
  3. Add an event handler to the consolidator.
  4. _consolidator.DataConsolidated += ConsolidationHandler;
    self._consolidator.data_consolidated += self._consolidation_handler

    LEAN passes consolidated bars to the consolidator event handler in your algorithm. The most common error when creating consolidators is to put parenthesis () at the end of your method name when setting the event handler of the consolidator. If you use parenthesis, the method executes and the result is passed as the event handler instead of the method itself. Remember to pass the name of your method to the event system. Specifically, it should be ConsolidationHandlerself._consolidation_handler, not ConsolidationHandler()self._consolidation_handler().

  5. Define the consolidation handler.
  6. void ConsolidationHandler(object sender, RenkoBar consolidatedBar)
    {
    
    }
    def _consolidation_handler(self, sender: object, consolidated_bar: RenkoBar) -> None:
        pass

    The consolidation event handler receives bars when the price movement forms a new classic Renko bar.

  7. Update the consolidator.
  8. You can automatically or manually update the consolidator.

    • Automatic Updates
    • To automatically update a consolidator with data from the security subscription, call the AddConsolidatoradd_consolidator method of the Subscription Manager.

      self.subscription_manager.add_consolidator(self._symbol, self._consolidator)
      SubscriptionManager.AddConsolidator(_symbol, _consolidator);
    • Manual Updates
    • Manual updates let you control when the consolidator updates and what data you use to update it. If you need to warm up a consolidator with data outside of the warm-up period, you can manually update the consolidator. To manually update a consolidator, call its Updateupdate method with a TradeBar object. You can update the consolidator with data from the Slice object in the OnDataon_data method or with data from a history request.

      # Example 1: Update the consolidator with data from the Slice object
      def on_data(self, slice: Slice) -> None:
          trade_bar = slice.bars[self._symbol]
          self._consolidator.update(trade_bar)
      
      # Example 2: Update the consolidator with data from a history request
      history = self.history[TradeBar](self._symbol, 30, Resolution.MINUTE)
      for trade_bar in history:
          self._consolidator.update(trade_bar)
      // Example 1: Update the consolidator with data from the Slice object
      public override void OnData(Slice slice)
      {
          var tradeBar = slice.Bars[_symbol];
          _consolidator.Update(tradeBar);
      }
      
      // Example 2: Update the consolidator with data from a history request
      var history = History<TradeBar>(_symbol, 30, Resolution.Minute);
      foreach (var tradeBar in history)
      {
          _consolidator.Update(tradeBar);
      }
  9. If you create consolidators for securities in a dynamic universe and register them for automatic updates, remove the consolidator when the security leaves the universe.
  10. SubscriptionManager.RemoveConsolidator(_symbol, _consolidator);
    self.subscription_manager.remove_consolidator(self._symbol, self._consolidator)

    If you have a dynamic universe and don't remove consolidators, they compound internally, causing your algorithm to slow down and eventually die once it runs out of RAM. For an example of removing consolidators from universe subscriptions, see the GasAndCrudeOilEnergyCorrelationAlphaGasAndCrudeOilEnergyCorrelationAlpha in the LEAN GitHub repository.

Consolidate Quote Bars

QuoteBar consolidators aggregate QuoteBar objects into RenkoBar objects. Follow these steps to create and manage a QuoteBar consolidator based on the preceding Renko bar rules:

  1. Create the consolidator.
  2. To create a classic Renko consolidator, pass the bar size to the ClassicRenkoConsolidator constructor.

    // Create a Classic Renko consolidator that emits a bar when the price moves $1
    _consolidator = new ClassicRenkoConsolidator(1m);
    # Create a Classic Renko consolidator that emits a bar when the price moves $1
    self._consolidator = ClassicRenkoConsolidator(1)

    The ClassicRenkoConsolidator has the following default behavior:

    • It uses the Valuevalue property of the IBaseData object it receives to build the Renko bars
    • It ignores the volume of the input data
    • It enforces the open and close of each bar to be a multiple of the bar size

    The following arguments enable you to create Renko bars that aggregate the excess liquidity on the bid.

    self._consolidator = ClassicRenkoConsolidator(10, lambda data: data.value, lambda data: data.last_bid_size - data.last_ask_size)
    _consolidator = new ClassicRenkoConsolidator(10, null, 
        data => (data as QuoteBar).LastBidSize - (data as QuoteBar).LastAskSize);

    To relax the requirement that the open and close of the Renko bars must be a multiple of bar size, disable the evenBarseven_bars argument. If you disable evenBarseven_bars, the open value of the first Renko bar is set to the first value from the selector. The following opening and closing Renko bar values are all multiples of the first value from the selector

    self._consolidator = ClassicRenkoConsolidator(1, even_bars=False)
    _consolidator = new ClassicRenkoConsolidator(1m, evenBars: false);
  3. Add an event handler to the consolidator.
  4. _consolidator.DataConsolidated += ConsolidationHandler;
    self._consolidator.data_consolidated += self._consolidation_handler

    LEAN passes consolidated bars to the consolidator event handler in your algorithm. The most common error when creating consolidators is to put parenthesis () at the end of your method name when setting the event handler of the consolidator. If you use parenthesis, the method executes and the result is passed as the event handler instead of the method itself. Remember to pass the name of your method to the event system. Specifically, it should be ConsolidationHandlerself._consolidation_handler, not ConsolidationHandler()self._consolidation_handler().

  5. Define the consolidation handler.
  6. void ConsolidationHandler(object sender, RenkoBar consolidatedBar)
    {
    
    }
    def _consolidation_handler(self, sender: object, consolidated_bar: RenkoBar) -> None:
        pass

    The consolidation event handler receives bars when the price movement forms a new classic Renko bar.

  7. Update the consolidator.
  8. You can automatically or manually update the consolidator.

    • Automatic Updates
    • To automatically update a consolidator with data from the security subscription, call the AddConsolidatoradd_consolidator method of the Subscription Manager.

      self.subscription_manager.add_consolidator(self._symbol, self._consolidator)
      SubscriptionManager.AddConsolidator(_symbol, _consolidator);
    • Manual Updates
    • Manual updates let you control when the consolidator updates and what data you use to update it. If you need to warm up a consolidator with data outside of the warm-up period, you can manually update the consolidator. To manually update a consolidator, call its Updateupdate method with a QuoteBar object. You can update the consolidator with data from the Slice object in the OnDataon_data method or with data from a history request.

      # Example 1: Update the consolidator with data from the Slice object
      def on_data(self, slice: Slice) -> None:
          quote_bar = slice.quote_bars[self._symbol]
          self._consolidator.update(quote_bar)
      
      # Example 2: Update the consolidator with data from a history request
      history = self.history[QuoteBar](self._symbol, 30, Resolution.MINUTE)
      for quote_bar in history:
          self._consolidator.update(quote_bar)
      // Example 1: Update the consolidator with data from the Slice object
      public override void OnData(Slice slice)
      {
          var quoteBar = slice.QuoteBars[_symbol];
          _consolidator.Update(quoteBar);
      }
      
      // Example 2: Update the consolidator with data from a history request
      var history = History<QuoteBar>(_symbol, 30, Resolution.Minute);
      foreach (var quoteBar in history)
      {
          _consolidator.Update(quoteBar);
      }
  9. If you create consolidators for securities in a dynamic universe and register them for automatic updates, remove the consolidator when the security leaves the universe.
  10. SubscriptionManager.RemoveConsolidator(_symbol, _consolidator);
    self.subscription_manager.remove_consolidator(self._symbol, self._consolidator)

    If you have a dynamic universe and don't remove consolidators, they compound internally, causing your algorithm to slow down and eventually die once it runs out of RAM. For an example of removing consolidators from universe subscriptions, see the GasAndCrudeOilEnergyCorrelationAlphaGasAndCrudeOilEnergyCorrelationAlpha in the LEAN GitHub repository.

Consolidate Trade Ticks

Tick consolidators aggregate Tick objects into RenkoBar objects. Follow these steps to create and manage a Tick consolidator based on the preceding Renko bar rules:

  1. Create the consolidator.
  2. To create a classic Renko consolidator, pass the bar size to the ClassicRenkoConsolidator constructor.

    // Create a Classic Renko consolidator that emits a bar when the price moves $1
    _consolidator = new ClassicRenkoConsolidator(1m);
    # Create a Classic Renko consolidator that emits a bar when the price moves $1
    self._consolidator = ClassicRenkoConsolidator(1)

    The ClassicRenkoConsolidator has the following default behavior:

    • It uses the Valuevalue property of the IBaseData object it receives to build the Renko bars
    • It ignores the volume of the input data
    • It enforces the open and close of each bar to be a multiple of the bar size

    To relax the requirement that the open and close of the Renko bars must be a multiple of bar size, disable the evenBarseven_bars argument. If you disable evenBarseven_bars, the open value of the first Renko bar is set to the first value from the selector. The following opening and closing Renko bar values are all multiples of the first value from the selector

    self._consolidator = ClassicRenkoConsolidator(1, even_bars=False)
    _consolidator = new ClassicRenkoConsolidator(1m, evenBars: false);
  3. Add an event handler to the consolidator.
  4. _consolidator.DataConsolidated += ConsolidationHandler;
    self._consolidator.data_consolidated += self._consolidation_handler

    LEAN passes consolidated bars to the consolidator event handler in your algorithm. The most common error when creating consolidators is to put parenthesis () at the end of your method name when setting the event handler of the consolidator. If you use parenthesis, the method executes and the result is passed as the event handler instead of the method itself. Remember to pass the name of your method to the event system. Specifically, it should be ConsolidationHandlerself._consolidation_handler, not ConsolidationHandler()self._consolidation_handler().

  5. Define the consolidation handler.
  6. void ConsolidationHandler(object sender, RenkoBar consolidatedBar)
    {
    
    }
    def _consolidation_handler(self, sender: object, consolidated_bar: RenkoBar) -> None:
        pass

    The consolidation event handler receives bars when the price movement forms a new classic Renko bar.

  7. Update the consolidator.
  8. You can automatically or manually update the consolidator.

    • Automatic Updates
    • To automatically update a consolidator with data from the security subscription, call the AddConsolidatoradd_consolidator method of the Subscription Manager.

      self.subscription_manager.add_consolidator(self._symbol, self._consolidator)
      SubscriptionManager.AddConsolidator(_symbol, _consolidator);
    • Manual Updates
    • Manual updates let you control when the consolidator updates and what data you use to update it. If you need to warm up a consolidator with data outside of the warm-up period, you can manually update the consolidator. To manually update a consolidator, call its Updateupdate method with a Tick object. You can update the consolidator with data from the Slice object in the OnDataon_data method or with data from a history request.

      # Example 1: Update the consolidator with data from the Slice object
      def on_data(self, slice: Slice) -> None:
          ticks = slice.ticks[self._symbol]
          for tick in ticks:
              self._consolidator.update(tick)
      
      # Example 2: Update the consolidator with data from a history request
      ticks = self.history[Tick](self._symbol, timedelta(minutes=3), Resolution.TICK)
      for tick in ticks:
          self._consolidator.update(tick)
      // Example 1: Update the consolidator with data from the Slice object
      public override void OnData(Slice slice)
      {
          var ticks = slice.Ticks[_symbol];
          foreach (var tick in ticks)
          {
          	_consolidator.Update(tick);
          }
      }
      
      // Example 2: Update the consolidator with data from a history request
      var ticks = History<Tick>(_symbol, TimeSpan.FromMinutes(3), Resolution.Tick);
      foreach (var tick in ticks)
      {
          _consolidator.Update(tick);
      }
  9. If you create consolidators for securities in a dynamic universe and register them for automatic updates, remove the consolidator when the security leaves the universe.
  10. SubscriptionManager.RemoveConsolidator(_symbol, _consolidator);
    self.subscription_manager.remove_consolidator(self._symbol, self._consolidator)

    If you have a dynamic universe and don't remove consolidators, they compound internally, causing your algorithm to slow down and eventually die once it runs out of RAM. For an example of removing consolidators from universe subscriptions, see the GasAndCrudeOilEnergyCorrelationAlphaGasAndCrudeOilEnergyCorrelationAlpha in the LEAN GitHub repository.

Consolidate Quote Ticks

Tick quote bar consolidators aggregate Tick objects that represent quotes into RenkoBar objects. Follow these steps to create and manage a Tick quote bar consolidator based on the preceding Renko bar rules:

  1. Create the consolidator.
  2. To create a classic Renko consolidator, pass the bar size to the ClassicRenkoConsolidator constructor.

    // Create a Classic Renko consolidator that emits a bar when the price moves $1
    _consolidator = new ClassicRenkoConsolidator(1m);
    # Create a Classic Renko consolidator that emits a bar when the price moves $1
    self._consolidator = ClassicRenkoConsolidator(1)

    The ClassicRenkoConsolidator has the following default behavior:

    • It uses the Valuevalue property of the IBaseData object it receives to build the Renko bars
    • It ignores the volume of the input data
    • It enforces the open and close of each bar to be a multiple of the bar size

    To relax the requirement that the open and close of the Renko bars must be a multiple of bar size, disable the evenBarseven_bars argument. If you disable evenBarseven_bars, the open value of the first Renko bar is set to the first value from the selector. The following opening and closing Renko bar values are all multiples of the first value from the selector

    self._consolidator = ClassicRenkoConsolidator(1, even_bars=False)
    _consolidator = new ClassicRenkoConsolidator(1m, evenBars: false);
  3. Add an event handler to the consolidator.
  4. _consolidator.DataConsolidated += ConsolidationHandler;
    self._consolidator.data_consolidated += self._consolidation_handler

    LEAN passes consolidated bars to the consolidator event handler in your algorithm. The most common error when creating consolidators is to put parenthesis () at the end of your method name when setting the event handler of the consolidator. If you use parenthesis, the method executes and the result is passed as the event handler instead of the method itself. Remember to pass the name of your method to the event system. Specifically, it should be ConsolidationHandlerself._consolidation_handler, not ConsolidationHandler()self._consolidation_handler().

  5. Define the consolidation handler.
  6. void ConsolidationHandler(object sender, RenkoBar consolidatedBar)
    {
    
    }
    def _consolidation_handler(self, sender: object, consolidated_bar: RenkoBar) -> None:
        pass

    The consolidation event handler receives bars when the price movement forms a new classic Renko bar.

  7. Update the consolidator.
  8. You can automatically or manually update the consolidator.

    • Automatic Updates
    • To automatically update a consolidator with data from the security subscription, call the AddConsolidatoradd_consolidator method of the Subscription Manager.

      self.subscription_manager.add_consolidator(self._symbol, self._consolidator)
      SubscriptionManager.AddConsolidator(_symbol, _consolidator);
    • Manual Updates
    • Manual updates let you control when the consolidator updates and what data you use to update it. If you need to warm up a consolidator with data outside of the warm-up period, you can manually update the consolidator. To manually update a consolidator, call its Updateupdate method with a Tick object. You can update the consolidator with data from the Slice object in the OnDataon_data method or with data from a history request.

      # Example 1: Update the consolidator with data from the Slice object
      def on_data(self, slice: Slice) -> None:
          ticks = slice.ticks[self._symbol]
          for tick in ticks:
              self._consolidator.update(tick)
      
      # Example 2: Update the consolidator with data from a history request
      ticks = self.history[Tick](self._symbol, timedelta(minutes=3), Resolution.TICK)
      for tick in ticks:
          self._consolidator.update(tick)
      // Example 1: Update the consolidator with data from the Slice object
      public override void OnData(Slice slice)
      {
          var ticks = slice.Ticks[_symbol];
          foreach (var tick in ticks)
          {
          	_consolidator.Update(tick);
          }
      }
      
      // Example 2: Update the consolidator with data from a history request
      var ticks = History<Tick>(_symbol, TimeSpan.FromMinutes(3), Resolution.Tick);
      foreach (var tick in ticks)
      {
          _consolidator.Update(tick);
      }
  9. If you create consolidators for securities in a dynamic universe and register them for automatic updates, remove the consolidator when the security leaves the universe.
  10. SubscriptionManager.RemoveConsolidator(_symbol, _consolidator);
    self.subscription_manager.remove_consolidator(self._symbol, self._consolidator)

    If you have a dynamic universe and don't remove consolidators, they compound internally, causing your algorithm to slow down and eventually die once it runs out of RAM. For an example of removing consolidators from universe subscriptions, see the GasAndCrudeOilEnergyCorrelationAlphaGasAndCrudeOilEnergyCorrelationAlpha in the LEAN GitHub repository.

Reset Consolidators

To reset a consolidator, call its Resetreset method.

self._consolidator.reset() 
_consolidator.Reset();

If you are live trading Equities or backtesting Equities without the adjusted data normalization mode, reset your consolidators when splits and dividends occur. When a split or dividend occurs while the consolidator is in the process of building a bar, the open, high, and low may reflect prices from before the split or dividend. To avoid issues, call the consolidator's Resetreset method and then warm it up with ScaledRawSCALED_RAW data from a history request.

def on_data(self, data: Slice):
    # When a split or dividend occurs...
    if (data.splits.contains_key(self._symbol) and data.splits[self._symbol].type == SplitType.SPLIT_OCCURRED or 
        data.dividends.contains_key(self._symbol)):
        # If the consolidator is working on a bar...
        if self._consolidator.working_data:
            # Get adjusted prices for the time period of the working bar.
            history = self.history[TradeBar](self._symbol, self._consolidator.working_data.time, self.time, data_normalization_mode=DataNormalizationMode.SCALED_RAW)
            # Reset the consolidator.
            self._consolidator.reset()
            # Warm-up the consolidator with the adjusted price data.
            for bar in history:
                self._consolidator.update(bar)
public override void OnData(Slice data)
{
    // When a split or dividend occurs...
    if ((data.Splits.ContainsKey(_symbol) && data.Splits[_symbol].Type == SplitType.SplitOccurred) ||
        data.Dividends.ContainsKey(_symbol))
    {
        // If the consolidator is working on a bar...
        if (_consolidator.WorkingData != null)
        {
            // Get adjusted prices for the time period of the working bar.
            var history = History<TradeBar>(_symbol, _consolidator.WorkingData.Time, Time, dataNormalizationMode: DataNormalizationMode.ScaledRaw);
            // Reset the consolidator.
            _consolidator.Reset();
            // Warm-up the consolidator with the adjusted price data.
            foreach (var bar in history)
            {
                _consolidator.Update(bar);
            }
        }
    }
}

Examples

The following examples demonstrate some common practices for implementing classic renko consolidator.

Example 1: 10 Dollar Bar Range SMA Cross

The following algorithm creates a dollar bar for SPY. Then, for each 10-dollar bar, we find their range (high - low) and feed to an SMA indicator, such that we obtain a trend indicator of the range of SPY. We trade VXX as the proxy of the SPY volatility based on the trend of the range SMA.

public class ClassicRenkoBarConsolidatorAlgorithm : QCAlgorithm
{
    private Symbol _spy, _vxx;
    private ClassicRenkoConsolidator _consolidator;
    private SimpleMovingAverage _sma = new(10);
    private decimal _high = 0m, _low = 10000m;
    private int _count = 0;

    public override void Initialize()
    {
        SetStartDate(2022, 3, 1);
        SetEndDate(2022, 6, 1);
        
        // Request SPY data to feed the consolidators and indicators for trade signal generation.
        _spy = AddEquity("SPY", Resolution.Minute).Symbol;
        // Request VXX data for trading.
        _vxx = AddEquity("VXX", Resolution.Minute).Symbol;

        // Create a dollar bar of SPY to track the volatility.
        _consolidator = new ClassicRenkoConsolidator(1);
        _consolidator.DataConsolidated += OnConsolidated;

        // Subscribe the consolidators to SPY data for automatic updating.
        SubscriptionManager.AddConsolidator(_spy, _consolidator);

        _sma.Window.Size = 2;
        SetWarmUp(100);
    }

    private void OnConsolidated(object sender, TradeBar bar)
    {
        // Update the SPY range of the current batch.
        _high = Math.Max(_high, bar.High);
        _low = Math.Min(_low, bar.Low);
        _count++;

        // Update SMA of SPY range of the last 10 Renko bars.
        if (_count >= 10)
        {
            _sma.Update(bar.EndTime, _high - _low);
            // Reset high and low.
            _high = 0m;
            _low = 10000m;
            _count = 0;
        }
    }

    public override void OnData(Slice slice)
    {
        if (_sma.IsReady)
        {
            // If the range trend is increasing, buy VXX as a proxy for the increase in volatility.
            if (_sma > _sma.Previous && !Portfolio[_vxx].IsLong)
            {
                SetHoldings(_vxx, 0.5m);
            }
            // If the range trend is decreasing, sell VXX as a proxy for decreasing volatility.
            else if (_sma < _sma.Previous && !Portfolio[_vxx].IsShort)
            {
                SetHoldings(_vxx, -0.5m);
            }
        }
    }
}
class ClassicRenkoBarConsolidatorAlgorithm(QCAlgorithm):
    _high = 0
    _low = 10000
    _count = 0
    _sma = SimpleMovingAverage(10)

    def initialize(self) -> None:
        self.set_start_date(2022, 3, 1)
        self.set_end_date(2022, 6, 1)
        
        # Request SPY data to feed the consolidators and indicators for trade signal generation.
        self._spy = self.add_equity("SPY", Resolution.MINUTE).symbol
        # Request VXX data for trading.
        self._vxx = self.add_equity("VXX", Resolution.MINUTE).symbol

        # Create a dollar bar of SPY to track the volatility.
        self._consolidator = ClassicRenkoConsolidator(1)
        self._consolidator.data_consolidated += self.on_consolidated

        # Subscribe the consolidators to SPY data for automatic updating.
        self.subscription_manager.add_consolidator(self._spy, self._consolidator)

        self._sma.window.size = 2;
        self.set_warm_up(100)

    def on_consolidated(self, sender: object, bar: TradeBar) -> None:
        # Update the SPY range of the current batch.
        self._high = max(self._high, bar.high)
        self._low = min(self._low, bar.low)
        self._count += 1

        # Update SMA of SPY range of the last 10 Renko bars.
        if self._count >= 10:
            self._sma.update(bar.end_time, self._high - self._low)

            # Reset high and low.
            self._high = 0
            self._low = 10000
            self._count = 0

    def on_data(self, slice: Slice) -> None:
        if self._sma.is_ready:
            current = self._sma.current.value
            previous = self._sma.previous.value

            # If the range trend increases, buy VXX as a proxy for the increasing volatility.
            if current > previous and not self.portfolio[self._vxx].is_long:
                self.set_holdings(self._vxx, 0.5)
            # If the range trend decreases, sell VXX as a proxy for decreasing volatility.
            elif current < previous and not self.portfolio[self._vxx].is_short:
                self.set_holdings(self._vxx, -0.5)

Other Examples

For more examples, see the following algorithms:

You can also see our Videos. You can also get in touch with us via Discord.

Did you find this page helpful?

Contribute to the documentation: