Ejemplo n.º 1
0
    def _generate_exposure_values(self, model: AlphaModel, backtest_dates):
        current_exposures_values = pd.Series(
            index=pd.Index(self._tickers, name=TICKERS))
        current_exposures_values[:] = 0.0

        exposure_values_df = DataFrame(index=backtest_dates,
                                       columns=pd.Index(self._tickers,
                                                        name=TICKERS))

        for i, curr_datetime in enumerate(backtest_dates):
            new_exposures = pd.Series(index=self._tickers)
            self._timer.set_current_time(curr_datetime)

            for j, ticker, curr_exp_value in zip(count(), self._tickers,
                                                 current_exposures_values):
                curr_exp = Exposure(curr_exp_value)
                new_exp = model.calculate_exposure(ticker, curr_exp)
                new_exposures.iloc[j] = new_exp.value

            # assuming that we always follow the new_exposures from strategy, disregarding confidence levels
            # and expected moves, looking only at the suggested exposure
            current_exposures_values = new_exposures
            exposure_values_df.iloc[i, :] = current_exposures_values.iloc[:]

        return exposure_values_df
Ejemplo n.º 2
0
    def _get_current_exposure(self, ticker: Union[Ticker, FutureTicker], current_positions: List[Position]) -> Exposure:
        """
        Returns current exposure of the given ticker in the portfolio. Alpha model strategy assumes there should be only
        one position per ticker in the portfolio. In case of future tickers this may not always be true - e.g. in case
        if a certain future contract expires and the rolling occurs we may end up with two positions open, when the
        old contract could not have been sold at the initially desired time. This situation usually does not happen
        often nor last too long, as the strategy will try to close the remaining position as soon as possible.
        Therefore, the current exposure of the ticker is defined as the exposure of the most recently opened position.
        """
        if isinstance(ticker, FutureTicker):
            matching_positions = [position for position in current_positions if
                                  ticker.belongs_to_family(
                                      self._contract_ticker_mapper.contract_to_ticker(position.contract()))
                                  ]
            assert len(matching_positions) in [0, 1, 2], "The number of open positions for a ticker should be 0, 1 or 2"
            all_specific_tickers = [self._contract_ticker_mapper.contract_to_ticker(position.contract())
                                    for position in matching_positions]
            assert len(set(all_specific_tickers)) == len(all_specific_tickers), "The number of open positions for a " \
                                                                                "specific ticker should be 0 or 1"
        else:
            matching_positions = [position for position in current_positions
                                  if position.contract() == self._contract_ticker_mapper.ticker_to_contract(ticker)]
            assert len(matching_positions) in [0, 1], "The number of open positions for a ticker should be 0 or 1"

        if len(matching_positions) > 0:
            newest_position = max(matching_positions, key=lambda pos: pos.start_time)
            quantity = newest_position.quantity()
            current_exposure = Exposure(np.sign(quantity))
        else:
            current_exposure = Exposure.OUT

        return current_exposure
Ejemplo n.º 3
0
    def _get_current_exposure(self, ticker: Union[Ticker, FutureTicker], current_positions: List[Position]) -> Exposure:
        """
        Returns current exposure of the given ticker in the portfolio. Alpha model strategy assumes there should be only
        one position per ticker in the portfolio.

        In case of future tickers this may not always be true - e.g. in case if a certain future contract expires and
        the rolling occurs we may end up with two positions open, when the old contract could not have been sold at the
        initially desired time. This situation usually does not happen often nor last too long, as the strategy will try
        to close the remaining position as soon as possible. Because of that, the current exposure of the ticker is
        defined either as the exposure of current contract or (if current contract is not present in the portfolio)
        the exposure of the previous contract.
        """
        ticker_to_quantity = {position.ticker(): position.quantity() for position in current_positions}
        assert len(ticker_to_quantity.keys()) == len(current_positions), "There should be max 1 position open per" \
                                                                         " ticker"

        current_ticker = ticker.get_current_specific_ticker() if isinstance(ticker, FutureTicker) else ticker
        current_ticker_quantity = ticker_to_quantity.get(current_ticker, 0)

        # There are no positions open for the current (specific) contract, in case of Future Tickers it is possible that
        # there are still positions open for previous contracts - in that case exposure will be based on them
        if current_ticker_quantity == 0 and isinstance(ticker, FutureTicker):
            matching_positions = [p for p in current_positions if ticker.belongs_to_family(p.ticker())]

            if len(matching_positions) > 1:
                matching_tickers = [p.ticker().as_string() for p in matching_positions]
                raise AssertionError(
                    "There should be no more then 1 position open for an already expired contract for a"
                    " future ticker. Detected positions open for the following contracts: {}.".format(
                        ", ".join(matching_tickers)))

            current_ticker_quantity = 0 if not matching_positions else matching_positions[0].quantity()

        current_exposure = Exposure(np.sign(current_ticker_quantity))
        return current_exposure
Ejemplo n.º 4
0
 def calculate_exposure(self, ticker: Ticker,
                        current_exposure: Exposure) -> Exposure:
     try:
         current_time = self.timer.now() + RelativeDelta(hour=0, minute=0, second=0) \
             if self.frequency <= Frequency.DAILY else self.timer.now()
         return Exposure(self.trading_scenarios.loc[current_time, ticker])
     except KeyError:
         return current_exposure
Ejemplo n.º 5
0
    def _get_current_exposure(contract: Contract,
                              current_positions: List[Position]) -> Exposure:
        matching_position_quantities = [
            position.quantity() for position in current_positions
            if position.contract() == contract
        ]

        assert len(matching_position_quantities) in [0, 1]
        quantity = next(iter(matching_position_quantities), 0)
        current_exposure = Exposure(np.sign(quantity))
        return current_exposure
Ejemplo n.º 6
0
    def _generate_exposure_values(self, config: FastAlphaModelTesterConfig,
                                  data_handler: FastDataHandler,
                                  tickers: Sequence[Ticker]):
        """
        For the given Alpha model and its parameters, generates the dataframe containing all exposure values, that
        will be returned by the model through signals.
        """

        model = config.generate_model(data_handler)

        current_exposures_values = QFSeries(
            index=pd.Index(tickers, name=TICKERS))
        current_exposures_values[:] = 0.0

        backtest_dates = pd.date_range(self._start_date,
                                       self._end_date,
                                       freq="B")

        exposure_values_df = QFDataFrame(index=backtest_dates,
                                         columns=pd.Index(tickers,
                                                          name=TICKERS))

        for ticker in tickers:
            if isinstance(ticker, FutureTicker):
                # Even if the tickers were already initialize, during pickling process, the data handler and timer
                # information is lost
                ticker.initialize_data_provider(self._timer, data_handler)

        for i, curr_datetime in enumerate(backtest_dates):
            new_exposures = QFSeries(index=tickers)
            self._timer.set_current_time(curr_datetime)

            for j, ticker, curr_exp_value in zip(count(), tickers,
                                                 current_exposures_values):
                curr_exp = Exposure(curr_exp_value) if is_finite_number(
                    curr_exp_value) else None
                try:
                    new_exp = model.calculate_exposure(ticker, curr_exp)
                except NoValidTickerException:
                    new_exp = None
                new_exposures.iloc[
                    j] = new_exp.value if new_exp is not None else None

            # assuming that we always follow the new_exposures from strategy, disregarding confidence levels
            # and expected moves, looking only at the suggested exposure
            current_exposures_values = new_exposures
            exposure_values_df.iloc[i, :] = current_exposures_values.iloc[:]

        exposure_values_df = exposure_values_df.dropna(axis=1, how="all")
        return exposure_values_df