Example #1
0
    def _atr_fraction_at_risk(self, ticker, time_period):
        """
        Parameters
        ----------
        ticker
            Ticker for which the calculation should be made
        time_period
            time period in days for which the ATR is calculated

        Returns
        -------
        float
            fraction_at_risk value for an AlphaModel and a Ticker, calculated as Normalized Average True Range
            multiplied by the risk_estimation_factor, being a property of each AlphaModel:
            fraction_at_risk = ATR / last_close * risk_estimation_factor
        """
        num_of_bars_needed = time_period + 1
        fields = [PriceField.High, PriceField.Low, PriceField.Close]
        try:
            prices_df = self.data_provider.historical_price(
                ticker, fields, num_of_bars_needed)
            fraction_at_risk = average_true_range(
                prices_df, normalized=True) * self.risk_estimation_factor
            return fraction_at_risk
        except ValueError:
            self.logger.error(
                f"Could not calculate the fraction_at_risk for the ticker {ticker.name}",
                exc_info=True)
            return nan
Example #2
0
    def test_alpha_model__calculate_fraction_at_risk(self):
        data_handler = MagicMock()
        prices_df = PricesDataFrame.from_records(data=[(6.0, 4.0, 5.0) for _ in range(10)],
                                                 columns=[PriceField.High, PriceField.Low, PriceField.Close])
        data_handler.historical_price.return_value = prices_df
        atr = average_true_range(prices_df, normalized=True)
        risk_estimation_factor = 3

        alpha_model = AlphaModel(risk_estimation_factor=risk_estimation_factor, data_provider=data_handler)
        fraction_at_risk = alpha_model.calculate_fraction_at_risk(self.ticker)
        self.assertEqual(risk_estimation_factor * atr, fraction_at_risk)
Example #3
0
    def compute_atr(self, prices_df: PricesDataFrame):
        try:
            prices_df = prices_df[[
                PriceField.Close, PriceField.Open, PriceField.High,
                PriceField.Low
            ]]
            prices_df = prices_df.dropna(how='all').fillna(
                method='ffill').dropna()
            #   Compute the ATR
            atr_values = average_true_range(
                prices_df.iloc[-self.num_of_bars_atr:], normalized=True)
        except Exception:
            raise NotEnoughDataException(
                "Not enough data to compute the average true range")

        return atr_values
Example #4
0
    def _atr_fraction_at_risk(self, ticker, time_period):
        """
        Parameters
        ----------
        ticker
            Ticker for which the calculation should be made
        time_period
            time period in days for which the ATR is calculated

        Returns
        -------
            fraction_at_risk value for an AlphaModel and a Ticker, calculated as Normalized Average True Range
            multiplied by the risk_estimation_factor, being a property of each AlphaModel:
            fraction_at_risk = ATR / last_close * risk_estimation_factor
        """
        num_of_bars_needed = time_period + 1
        fields = [PriceField.High, PriceField.Low, PriceField.Close]
        prices_df = self.data_handler.historical_price(ticker, fields,
                                                       num_of_bars_needed)
        fraction_at_risk = average_true_range(
            prices_df, normalized=True) * self.risk_estimation_factor
        return fraction_at_risk
Example #5
0
    def calculate_exposure(self, ticker: FutureTicker,
                           current_exposure: Exposure) -> Exposure:
        num_of_bars_needed = self.slow_time_period
        current_time = self.timer.now()

        # Compute the start time
        start_time = current_time - RelativeDelta(days=num_of_bars_needed +
                                                  100)

        if self.futures_chain is None:
            # Create Futures Chain object
            self.futures_chain = FuturesChain(ticker, self.data_handler)

        # Get the data frame containing High, Low, Close prices
        data_frame = self.futures_chain.get_price(
            [PriceField.High, PriceField.Low, PriceField.Close], start_time,
            current_time)
        data_frame = data_frame.dropna(how='all').fillna(method='pad')

        close_tms = data_frame[PriceField.Close]
        close_tms = close_tms.iloc[-self.slow_time_period:]

        try:
            # Compute the ATR
            atr_df = data_frame[-num_of_bars_needed:]
            self.average_true_range = average_true_range(atr_df,
                                                         normalized=True)

            ############################
            #      Opening position    #
            ############################

            current_price = close_tms.iloc[-1]

            # Compute the fast and slow simple moving averages
            fast_ma = sum(close_tms.iloc[-self.fast_time_period:]
                          ) / self.fast_time_period
            slow_ma = sum(close_tms) / self.slow_time_period

            if fast_ma > slow_ma:
                # Long entries are only allowed if the fast moving average is above the slow moving average.
                # If today’s closing price is the highest close in the past 50 days, we buy.
                highest_price = max(close_tms[-self.fast_time_period:])
                if current_price >= highest_price:
                    if current_exposure == Exposure.OUT:
                        self.time_of_opening_position = close_tms.index[-1]
                    return Exposure.LONG
            else:
                # Short entries are only allowed if the fast moving average is below the slow moving average.
                # If today’s closing price is the lowest close in the past 50 days, we sell.
                lowest_price = min(close_tms[-self.fast_time_period:])
                if current_price <= lowest_price:
                    if current_exposure == Exposure.OUT:
                        self.time_of_opening_position = close_tms.index[-1]
                    return Exposure.SHORT

            ############################
            #     Closing position     #
            ############################

            if current_exposure == Exposure.LONG:
                # A long position is closed when it has moved three ATR units down from its highest closing price
                # since the position was opened.
                close_prices = close_tms.loc[
                    self.time_of_opening_position:].dropna()
                if current_price < max(close_prices) * (
                        1 -
                        self.risk_estimation_factor * self.average_true_range):
                    return Exposure.OUT

            elif current_exposure == Exposure.SHORT:
                # A short position is closed when it has moved three ATR units up from its lowest closing price
                # since the position was opened.
                close_prices = close_tms.loc[
                    self.time_of_opening_position:].dropna()
                if current_price > min(close_prices) * (
                        1 +
                        self.risk_estimation_factor * self.average_true_range):
                    return Exposure.OUT

        except (KeyError, ValueError):
            # No price at this day
            pass

        return current_exposure