def generate_recommendation(self):
        """
            Applies the price dispersion algorithm and sets the following 
            instance variables:

            self.recommendation_set
                A SecurityRecommendationSet object with the current 
                recommendation
            self.raw_dataframe
                Dataframe with all stocks sorted into deciles. Useful for
                displaying intermediate results.
            self.recommendation_dataframe
                A Dataframe containing just the recommended stocks

            Returns
            ------------
            None
        """

        financial_data = self.__load_financial_data__()

        self.raw_dataframe = pd.DataFrame(financial_data)
        pd.options.display.float_format = '{:.3f}'.format

        # sort the dataframe into deciles
        self.raw_dataframe['decile'] = pd.qcut(
            financial_data['dispersion_stdev_pct'],
            10,
            labels=False,
            duplicates='drop')
        self.raw_dataframe = self.raw_dataframe.sort_values(
            ['decile', 'analyst_expected_return'], ascending=(False, False))

        self.recommendation_dataframe = self.raw_dataframe.head(
            self.output_size).drop([
                'decile', 'target_price_avg', 'dispersion_stdev_pct',
                'analyst_expected_return'
            ],
                                   axis=1)

        # price the recommended securitues
        priced_securities = {}
        for row in self.recommendation_dataframe.itertuples(index=False):
            priced_securities[row.ticker] = row.analysis_price

        # determine the recommendation valid date range
        valid = self.analysis_end_date + timedelta(days=1)

        (valid_from, valid_to) = intrinio_util.get_month_date_range(
            valid.year, valid.month)

        self.recommendation_set = SecurityRecommendationSet.from_parameters(
            datetime.now(), valid_from, valid_to, self.analysis_end_date,
            self.STRATEGY_NAME, "US Equities", priced_securities)
    def test_month_range_invaid_month(self):
        with self.assertRaises(ValidationError):
            intrinio_util.get_month_date_range(2019, 13)

        with self.assertRaises(ValidationError):
            intrinio_util.get_month_date_range(2019, 0)

        with self.assertRaises(ValidationError):
            intrinio_util.get_month_date_range(2019, -1)
    def __init__(self, ticker_list: list, data_year: int, data_month: int,
                 output_size: int):
        """
            Initializes the class with the ticker list, a year and a month.

            The year and month are used to set the context of the analysis,
            meaning that financial data will be used for that year/month.
            This is done to allow the analysis to be run in the past and test the
            quality of the results.


            Parameters
            ------------
            ticker_list : list of tickers to be included in the analisys
            ticker_source_name : The source of the ticker list. E.g. DOW30, or SP500
            year : analysis year
            month : analysis month
            output_size : number of recommended securities that will be returned
                by this strategy

        """

        if (ticker_list is None or len(ticker_list) == 0):
            raise ValidationError("No ticker list was supplied", None)

        if len(ticker_list) < 2:
            raise ValidationError("You must supply at least 2 ticker symbols",
                                  None)

        if output_size <= 0:
            raise ValidationError("Output size must be at least 1", None)

        (self.analysis_start_date,
         self.analysis_end_date) = intrinio_util.get_month_date_range(
             data_year, data_month)

        if (self.analysis_end_date > datetime.now()):
            logging.debug("Setting analysis end date to 'today'")
            self.analysis_end_date = datetime.now()

        self.ticker_list = ticker_list

        self.output_size = output_size
        self.data_date = "%d-%d" % (data_year, data_month)

        self.recommendation_set = None
        self.raw_dataframe = None
        self.recommendation_dataframe = None
Example #4
0
    def backtest(year: int, month: int):
        log.info("Peforming backtest for %d/%d" % (month, year))
        data_end_date = intrinio_util.get_month_date_range(year, month)[1]

        strategy = PriceDispersionStrategy(ticker_list, year, month,
                                           output_size)
        strategy.generate_recommendation()

        date_1m = data_end_date + timedelta(days=30)
        date_2m = data_end_date + timedelta(days=60)
        date_3m = data_end_date + timedelta(days=90)

        portfolio_1m = calculator.mark_to_market(
            strategy.recommendation_dataframe,
            date_1m)['actual_return'].mean() * 100
        portfolio_2m = calculator.mark_to_market(
            strategy.recommendation_dataframe,
            date_2m)['actual_return'].mean() * 100
        portfolio_3m = calculator.mark_to_market(
            strategy.recommendation_dataframe,
            date_3m)['actual_return'].mean() * 100

        all_stocks_1m = calculator.mark_to_market(
            strategy.raw_dataframe, date_1m)['actual_return'].mean() * 100
        all_stocks_2m = calculator.mark_to_market(
            strategy.raw_dataframe, date_2m)['actual_return'].mean() * 100
        all_stocks_3m = calculator.mark_to_market(
            strategy.raw_dataframe, date_3m)['actual_return'].mean() * 100

        backtest_report['investment_period'].append(
            data_end_date.strftime('%Y/%m'))
        backtest_report['ticker_sample_size'].append(
            len(strategy.raw_dataframe))

        backtest_report['avg_ret_1M'].append(all_stocks_1m)
        backtest_report['sel_ret_1M'].append(portfolio_1m)
        backtest_report['avg_ret_2M'].append(all_stocks_2m)
        backtest_report['sel_ret_2M'].append(portfolio_2m)
        backtest_report['avg_ret_3M'].append(all_stocks_3m)
        backtest_report['sel_ret_3M'].append(portfolio_3m)
 def test_month_range_invaid_year(self):
     with self.assertRaises(ValidationError):
         intrinio_util.get_month_date_range(0, 2)