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_is_current_current_date_single(self): # Create a recommendation set from the past (2019/8) recommendation_set = SecurityRecommendationSet.from_parameters( datetime(2020, 3, 1, 4, 56, 57, tzinfo=timezone.utc), date(2019, 8, 1), date(2019, 8, 1), date(2019, 8, 1), "PRICE_DISPERSION", "US Equities", { "GE": 123.45, "INTC": 123.45, "AAPL": 123.45 }) self.assertTrue(recommendation_set.is_current(date(2019, 8, 1)))
def test_notify_new_recommendation_with_boto_error(self): with patch.object(aws_service_wrapper, 'cf_read_export_value', return_value="some_sns_arn"), \ patch.object(aws_service_wrapper, 'sns_publish_notification', side_effect=AWSError("test exception", None)): notification_list = [] notification_list.append(SecurityRecommendationSet.from_parameters(datetime.now(), datetime.now( ), datetime.now(), datetime.now(), 'STRATEGY_NAME', 'US Equities', {'AAPL': 100})) with self.assertRaises(AWSError): recommendation_svc.notify_new_recommendation( notification_list, 'sa')
def generate_recommendation(self): ''' Analyzes all securitues supplied in the ticker list and returns a SecurityRecommendationSet object containing all stocks with a positive MACD crossover. These are stocks that are bullish and have positive momentum behind them. internally sets the self.recommendation_set object ''' analysis_data = { 'ticker_symbol': [], 'price': [], 'macd': [], 'signal': [], 'divergence': [], 'momentum': [] } recommended_securities = {} for ticker_symbol in self.ticker_list.ticker_symbols: (current_price, macd_line, signal_line) = self._read_price_metrics( ticker_symbol) buy_sell_indicator = self._analyze_security( current_price, macd_line, signal_line) analysis_data['ticker_symbol'].append(ticker_symbol) analysis_data['price'].append(current_price) analysis_data['macd'].append(macd_line) analysis_data['signal'].append(signal_line) analysis_data['divergence'].append(macd_line - signal_line) if buy_sell_indicator == True: analysis_data['momentum'].append("BULLISH") recommended_securities[ticker_symbol] = current_price else: analysis_data['momentum'].append("BEARISH") self.raw_dataframe = pd.DataFrame(analysis_data) self.raw_dataframe = self.raw_dataframe.sort_values( ['momentum', 'divergence'], ascending=(False, False)) valid_from = valid_to = self.analysis_date self.recommendation_set = SecurityRecommendationSet.from_parameters( datetime.now(), valid_from, valid_to, self.analysis_date, self.STRATEGY_NAME, "US_EQUITIES", recommended_securities )
def test_valid_parameters(self): SecurityRecommendationSet.from_parameters( datetime.now(), datetime.now(), datetime.now(), datetime.now(), 'STRATEGY_NAME', 'US Equities', {'AAPL': 100})
def test_invalid_parameters(self): ''' Combine these into a single test for brevity ''' with self.assertRaises(ValidationError): SecurityRecommendationSet.from_parameters(None, date.today(), date.today(), datetime.now(), 'STRATEGY_NAME', 'US Equities', {'AAPL': 100}) with self.assertRaises(ValidationError): SecurityRecommendationSet.from_parameters(datetime.now(), None, date.today(), date.today(), 'STRATEGY_NAME', 'US Equities', {'AAPL': 100}) with self.assertRaises(ValidationError): SecurityRecommendationSet.from_parameters(datetime.now(), date.today(), None, datetime.now(), 'STRATEGY_NAME', 'US Equities', {'AAPL': 100}) with self.assertRaises(ValidationError): SecurityRecommendationSet.from_parameters(datetime.now(), date.today(), date.today(), None, 'STRATEGY_NAME', 'US Equities', {'AAPL': 100}) with self.assertRaises(ValidationError): SecurityRecommendationSet.from_parameters(datetime.now(), date.today(), date.today(), date.today(), None, 'US Equities', {'AAPL': 100}) with self.assertRaises(ValidationError): SecurityRecommendationSet.from_parameters(datetime.now(), date.today(), date.today(), date.today(), 'STRATEGY_NAME', None, {'AAPL': 100}) with self.assertRaises(ValidationError): SecurityRecommendationSet.from_parameters(datetime.now(), date.today(), date.today(), date.today(), 'STRATEGY_NAME', 'US Equities', None) with self.assertRaises(ValidationError): SecurityRecommendationSet.from_parameters( datetime.now(), date.today(), date.today(), date.today(), 'STRATEGY_NAME', 'US Equities', "Not A Dictionary")