Esempio n. 1
0
    def updateParameters(self, zipline_data: BarData):
        """Update ETF parameters; specifically, the asset allocations weights,
        the log return (over the configuration lookback window), the variance,
        and the synthetic ETF prices over the lookback window.
        
        Arguments:
            zipline_data {BarData} -- Instance zipline data bundle.
        """

        # Get historical price data for lookback window from config
        historical_data = zipline_data.history(
            symbols(*self.tickers),
            'price',
            bar_count=config.setf_lookback_window,
            frequency=config.setf_data_frequency)

        # Filling na values
        historical_data = historical_data.fillna(method='bfill')
        historical_data = historical_data.fillna(method='ffill')

        # Computing prices, restructuring per the period in the configuration
        setf_prices = np.array([])
        first_run = True  # Flag for first run
        for idx, row in historical_data.iterrows():
            if (self.backtest_util.isRestructureTriggered(current_date=idx,
                                                          log_flag=False)
                    or first_run):
                # Recompute allocation weights
                alloc_weights = np.array(row / row.sum())
                # Update first run flag
                first_run = False
            # Computing synthetic ETF price
            setf_price = np.dot(alloc_weights, row.values)
            # Appending to prices array
            setf_prices = np.append(setf_prices, setf_price)

        if (np.count_nonzero(np.isnan(setf_prices)) > 0):
            logging.error('NA values detected in Synthetic ETF prices')
            raise Exception

        # Computing ETF log returns
        self.log_rets = np.diff(np.log(setf_prices))

        # Computing single-period ETF log return (sum of log returns)
        self.period_log_ret = np.sum(self.log_rets)

        # Computing ETF variance
        self.variance = np.var(self.log_rets)

        # Casting synthetic ETF prices to DataFrame with original index, binding
        self.setf_prices = pd.DataFrame(setf_prices,
                                        index=historical_data.index)
Esempio n. 2
0
    def test_old_new_data_api_paths(self):
        """
        Test that the new and old data APIs hit the same code paths.

        We want to ensure that the old data API(data[sid(N)].field and
        similar)  and the new data API(data.current(sid(N), field) and
        similar) hit the same code paths on the DataPortal.
        """
        test_start_minute = self.env.market_minutes_for_day(
            self.sim_params.trading_days[0]
        )[1]
        test_end_minute = self.env.market_minutes_for_day(
            self.sim_params.trading_days[0]
        )[-1]
        bar_data = BarData(
            self.data_portal,
            lambda: test_end_minute, "minute"
        )
        ohlcvp_fields = [
            "open",
            "high",
            "low"
            "close",
            "volume",
            "price",
        ]
        spot_value_meth = 'zipline.data.data_portal.DataPortal.get_spot_value'

        def assert_get_spot_value_called(fun, field):
            """
            Assert that get_spot_value was called during the execution of fun.

            Takes in a function fun and a string field.
            """
            with patch(spot_value_meth) as gsv:
                fun()
                gsv.assert_called_with(
                    self.asset1,
                    field,
                    test_end_minute,
                    'minute'
                )
        # Ensure that data.current(sid(n), field) has the same behaviour as
        # data[sid(n)].field.
        for field in ohlcvp_fields:
            assert_get_spot_value_called(
                lambda: getattr(bar_data[self.asset1], field),
                field,
            )
            assert_get_spot_value_called(
                lambda: bar_data.current(self.asset1, field),
                field,
            )

        history_meth = 'zipline.data.data_portal.DataPortal.get_history_window'

        def assert_get_history_window_called(fun, is_legacy):
            """
            Assert that get_history_window was called during fun().

            Takes in a function fun and a boolean is_legacy.
            """
            with patch(history_meth) as ghw:
                fun()
                # Slightly hacky, but done to get around the fact that
                # history( explicitly passes an ffill param as the last arg,
                # while data.history doesn't.
                if is_legacy:
                    ghw.assert_called_with(
                        [self.asset1, self.asset2, self.asset3],
                        test_end_minute,
                        5,
                        "1m",
                        "volume",
                        True
                    )
                else:
                    ghw.assert_called_with(
                        [self.asset1, self.asset2, self.asset3],
                        test_end_minute,
                        5,
                        "1m",
                        "volume",
                    )

        test_sim_params = SimulationParameters(
            period_start=test_start_minute,
            period_end=test_end_minute,
            data_frequency="minute",
            env=self.env
        )

        history_algorithm = self.create_algo(
            history_algo,
            sim_params=test_sim_params
        )
        assert_get_history_window_called(
            lambda: history_algorithm.run(self.data_portal),
            is_legacy=True
        )
        assert_get_history_window_called(
            lambda: bar_data.history(
                [self.asset1, self.asset2, self.asset3],
                "volume",
                5,
                "1m"
            ),
            is_legacy=False
        )