Example #1
0
    def zipline_initialize(context: TradingAlgorithm):
        """Zipline backtest initialization method override.

        Initializes context namespace variables used during the portfolio
        optimization, and sets zipline configuration options for the simulation.
        
        Arguments:
            context {TradingAlgorithm} -- Context variable for the algorithm
        """

        # Zipline context namespace variables
        context.first_run = True  # First run flag
        context.synthetics = dict(
        )  # Dictionary to store synthetic ETF objects
        context.port = MinimumVariance()  # Initializing portfolio

        # Enforcing long trades only
        # NOTE: This is commented out because of rounding bugs; i.e. when
        #       certain positions were reduced to 0, some of the rounding caused
        #       some positions to go to -1 shares. This is neglegible, and as
        #       the current optimization enforces no shorts, this
        #       condition is relaxed here.
        # set_long_only()

        # Setting the per-trade commission from config
        set_commission(PerDollar(cost=config.trade_commission))

        # Initializing utilities module
        context.util = Utilities()

        # Initializing bookkeeping module
        context.books = Bookkeeping()
Example #2
0
    def zipline_handle_data(context: TradingAlgorithm, data: BarData):
        """Zipline `handle_data` method override. Handles all trading
        operations for the algorithm. Additionally, this method also handles
        synthetic ETF initialization, portfolio balancing, and logging.

        In summary, this method initializes all synthetic ETFs on the first
        iteration, balances, and opens positions in the necessary assets. After
        that, it checks the current date of the simulation against the triggers
        for portfolio balancing and ETF restructuring provided in the
        configuration file to initialize a rebalancing or restructuring
        operation, respectively.
        
        Arguments:
            context {TradingAlgorithm} -- Zipline context namespace variable.
            data {BarData} -- Instance zipline data bundle.
        """

        # Reset log (to handle Zipline's forward-propagation behavior of the
        # `record(...)` function)
        context.books.cleanLog()

        # First run operations
        if (context.first_run):
            # Validate sector universe
            config.sector_universe = Backtest.validateSectorUniverse(
                candidate_sector_universe=config.sector_universe,
                zipline_data=data)

            # Building synthetic sector ETFs
            Backtest.buildSyntheticETFs(context=context, zipline_data=data)

            # Computing initial portfolio, updating positions
            Backtest.rebalancePortfolio(context=context,
                                        zipline_data=data,
                                        update_positions=True,
                                        log_commission=False)

            # Updating initial flags for rebalancing/restructuring trigger
            context.util.setInitialFlags()

            # Logging ETF prices
            context.books.etfDataLog(etf_prices=Backtest.getETFPrices(
                context, data),
                                     etf_weights=context.port_w)

            # Skip rest of logic for first iteration, update iteration flag
            context.first_run = False
            return

        # Portfolio Rebalancing
        if context.util.isRebalanceTriggered():
            Backtest.rebalancePortfolio(context=context,
                                        zipline_data=data,
                                        update_positions=True,
                                        log_commission=True)

        # Synthetic ETF restructuring
        if context.util.isRestructureTriggered():
            Backtest.restructureETF(context=context,
                                    zipline_data=data,
                                    update_positions=True,
                                    log_commission=True)

        # Log ETF prices
        context.books.etfDataLog(etf_prices=Backtest.getETFPrices(
            context, data),
                                 etf_weights=context.port_w)