def test_recommendation_set_price_date_during_analysisperiod(self): with patch.object(PriceDispersionStrategy, '_load_financial_data', return_value=self.financial_data): price_date = date(2020, 6, 10) strategy = PriceDispersionStrategy( TickerList.from_dict({ "list_name": "DOW30", "list_type": "US_EQUITIES", "comparison_symbol": "DIA", "ticker_symbols": ['AAPL', 'V'] }), '2020-06', price_date, 3) strategy.generate_recommendation() recommendation_set = strategy.recommendation_set self.assertEqual(recommendation_set.model['valid_from'], str(date(2020, 7, 1))) self.assertEqual(recommendation_set.model['valid_to'], str(date(2020, 7, 31))) self.assertEqual(recommendation_set.model['price_date'], str(date(2020, 6, 10)))
def test_from_configuration_invalid(self): with patch('support.constants.CONFIG_FILE_PATH', "./test/config-unittest-bad/"): with self.assertRaises(ValidationError): PriceDispersionStrategy.from_configuration( Configuration.from_local_config("bad-test-config.ini"), 'sa')
def test_api_exception(self): with patch.object(intrinio_data.COMPANY_API, 'get_company_historical_data', side_effect=ApiException("Not Found")): strategy = PriceDispersionStrategy(['1', '2'], 2020, 2, 1) with self.assertRaises(DataError): strategy.__load_financial_data__()
def test_api_exception(self): with patch.object(intrinio_data.COMPANY_API, 'get_company_historical_data', side_effect=ApiException("Not Found")): strategy = PriceDispersionStrategy( TickerList.from_dict({ "list_name": "DOW30", "list_type": "US_EQUITIES", "comparison_symbol": "DIA", "ticker_symbols": ['AAPL', 'V'] }), '2000-05', date(2000, 6, 10), 3) with self.assertRaises(DataError): strategy._load_financial_data()
def test_init_no_price_date(self): PriceDispersionStrategy( TickerList.from_dict({ "list_name": "DOW30", "list_type": "US_EQUITIES", "comparison_symbol": "DIA", "ticker_symbols": ['AAPL', 'V'] }), '2020-05', None, 3)
def test_init_enough_tickers(self): PriceDispersionStrategy( TickerList.from_dict({ "list_name": "DOW30", "list_type": "US_EQUITIES", "comparison_symbol": "DIA", "ticker_symbols": ['AAPL', 'V'] }), '2020-02', date(2020, 6, 10), 3)
def test_init_bad_period(self): with self.assertRaises(ValidationError): PriceDispersionStrategy( TickerList.from_dict({ "list_name": "DOW30", "list_type": "US_EQUITIES", "comparison_symbol": "DIA", "ticker_symbols": ['AAPL', 'V'] }), 'invalid_period', date(2020, 6, 10), 3)
def test_init_empty_ticker_list(self): with self.assertRaises(ValidationError): PriceDispersionStrategy( TickerList.from_dict({ "list_name": "DOW30", "list_type": "US_EQUITIES", "comparison_symbol": "DIA", "ticker_symbols": [] }), '2020-02', date(2020, 6, 10), 3)
def test_init_output_size_too_small(self): with self.assertRaises(ValidationError): PriceDispersionStrategy( TickerList.from_dict({ "list_name": "DOW30", "list_type": "US_EQUITIES", "comparison_symbol": "DIA", "ticker_symbols": ['AAPL', 'V'] }), '2020-02', date(2020, 6, 10), 0)
def backtest(analysis_period: str): log.info("Performing backtest for %s" % analysis_period) period = pd.Period(analysis_period) data_end_date = intrinio_util.get_month_period_range(period)[1] strategy = PriceDispersionStrategy( ticker_list, period, None, output_size) strategy.generate_recommendation() date_1m = get_nearest_business_date(data_end_date + timedelta(days=30)) date_2m = get_nearest_business_date(data_end_date + timedelta(days=60)) date_3m = get_nearest_business_date(data_end_date + timedelta(days=90)) portfolio_1m = calculator.mark_to_market( strategy.recommendation_dataframe, 'ticker', 'analysis_price', date_1m)['actual_return'].mean() * 100 portfolio_2m = calculator.mark_to_market( strategy.recommendation_dataframe, 'ticker', 'analysis_price', date_2m)['actual_return'].mean() * 100 portfolio_3m = calculator.mark_to_market( strategy.recommendation_dataframe, 'ticker', 'analysis_price', date_3m)['actual_return'].mean() * 100 all_stocks_1m = calculator.mark_to_market(strategy.raw_dataframe, 'ticker', 'analysis_price', date_1m)[ 'actual_return'].mean() * 100 all_stocks_2m = calculator.mark_to_market(strategy.raw_dataframe, 'ticker', 'analysis_price', date_2m)[ 'actual_return'].mean() * 100 all_stocks_3m = calculator.mark_to_market(strategy.raw_dataframe, 'ticker', 'analysis_price', 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 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_recommendation_set_price_date_before_analysisperiod(self): with patch.object(PriceDispersionStrategy, '_load_financial_data', return_value=self.financial_data): price_date = date(2020, 5, 10) with self.assertRaises(ValidationError): strategy = PriceDispersionStrategy( TickerList.from_dict({ "list_name": "DOW30", "list_type": "US_EQUITIES", "comparison_symbol": "DIA", "ticker_symbols": ['AAPL', 'V'] }), '2020-06', price_date, 3)
def test_from_configuration_valid(self): ticker_list = TickerList.from_local_file("%s/djia30.json" % (constants.APP_DATA_DIR)) with patch.object(util, 'get_business_date', return_value=date(2020, 6, 3)), \ patch.object(pd, 'to_datetime', return_value=datetime(2020, 6, 19)), \ patch.object(TickerList, 'from_s3', return_value=ticker_list): strategy = PriceDispersionStrategy.from_configuration( Configuration.from_local_config( constants.STRATEGY_CONFIG_FILE_NAME), 'sa') self.assertEqual(strategy.analysis_start_date, date(2020, 5, 1)) self.assertEqual(strategy.analysis_end_date, date(2020, 5, 31)) self.assertEqual(strategy.current_price_date, date(2020, 6, 3)) '''
def test_init_no_tickers(self): with self.assertRaises(ValidationError): PriceDispersionStrategy(None, 2020, 2, 1)
def test_init_output_size_too_small(self): with self.assertRaises(ValidationError): PriceDispersionStrategy(['1', '2'], 2020, 1, 0)
def test_init_too_few_tickers(self): with self.assertRaises(ValidationError): PriceDispersionStrategy(['AAPL'], 2020, 2, 1)
def test_init_enough_tickers(self): PriceDispersionStrategy(['1', '2'], 2020, 1, 1)
def main(): """ Main function for this script """ try: (environment, ticker_file_name, output_size, month, year, current_price_date, app_ns) = parse_params() log.info("Parameters:") log.info("Environment: %s" % environment) log.info("Ticker File: %s" % ticker_file_name) log.info("Output Size: %d" % output_size) log.info("Analysis Month: %d" % month) log.info("Analysis Year: %d" % year) if environment == "TEST": log.info("reading ticker file from local filesystem") ticker_list = TickerFile.from_local_file( constants.TICKER_DATA_DIR, ticker_file_name).ticker_list log.info("Performing Recommendation Algorithm") strategy = PriceDispersionStrategy(ticker_list, year, month, output_size) strategy.generate_recommendation() display_calculation_dataframe(month, year, strategy, current_price_date) else: # environment == "PRODUCTION" # test all connectivity upfront, so if there any issues # the problem becomes more apparent connector_test.test_aws_connectivity() connector_test.test_intrinio_connectivity() log.info("Reading ticker file from s3 bucket") ticker_list = TickerFile.from_s3_bucket(ticker_file_name, app_ns).ticker_list log.info("Loading existing recommendation set from S3") recommendation_set = None try: recommendation_set = SecurityRecommendationSet.from_s3(app_ns) except AWSError as awe: if not awe.resource_not_found(): raise awe log.info("No recommendation set was found in S3.") if recommendation_set == None \ or not recommendation_set.is_current(datetime.now()): log.info("Performing Recommendation Algorithm") strategy = PriceDispersionStrategy(ticker_list, year, month, output_size) strategy.generate_recommendation() recommendation_set = strategy.recommendation_set display_calculation_dataframe(month, year, strategy, current_price_date) recommendation_set.save_to_s3(app_ns) recommendation_svc.notify_new_recommendation( recommendation_set, app_ns) else: log.info( "Recommendation set is still valid. There is nothing to do" ) except Exception as e: stack_trace = traceback.format_exc() log.error("Could run script, because: %s" % (str(e))) log.error(stack_trace) if environment == "PRODUCTION": aws_service_wrapper.notify_error( e, "Securities Recommendation Service", stack_trace, app_ns)
def test_init_no_tickers(self): with self.assertRaises(ValidationError): PriceDispersionStrategy(None, '2020-02', date(2020, 6, 10), 3)
def main(): """ Main function for this script """ try: app_ns = parse_params() log.info("Parameters:") log.info("Application Namespace: %s" % app_ns) business_date = util.get_business_date( constants.BUSINESS_DATE_DAYS_LOOKBACK, constants.BUSINESS_DATE_CUTOVER_TIME) log.info("Business Date is: %s" % business_date) # test all connectivity upfront, so if there any issues # the problem becomes more apparent connector_test.test_aws_connectivity() connector_test.test_intrinio_connectivity() log.info('Loading Strategy Configuration "%s" from S3' % constants.STRATEGY_CONFIG_FILE_NAME) configuration = Configuration.try_from_s3( constants.STRATEGY_CONFIG_FILE_NAME, app_ns) log.info("Initalizing Trading Strategies") strategies = [ PriceDispersionStrategy.from_configuration(configuration, app_ns), MACDCrossoverStrategy.from_configuration(configuration, app_ns) ] notification_list = [] for strategy in strategies: recommendation_set = None try: log.info("Executing %s strategy" % strategy.STRATEGY_NAME) recommendation_set = SecurityRecommendationSet.from_s3( app_ns, strategy.S3_RECOMMENDATION_SET_OBJECT_NAME) except AWSError as awe: if not awe.resource_not_found(): raise awe log.info("No recommendation set was found in S3.") if recommendation_set == None \ or not recommendation_set.is_current(business_date): strategy.generate_recommendation() strategy.display_results() recommendation_set = strategy.recommendation_set recommendation_set.save_to_s3( app_ns, strategy.S3_RECOMMENDATION_SET_OBJECT_NAME) notification_list.append(recommendation_set) else: log.info( "Recommendation set is still valid. There is nothing to do") recommendation_svc.notify_new_recommendation( notification_list, app_ns) except Exception as e: stack_trace = traceback.format_exc() log.error("Could run script, because: %s" % (str(e))) log.error(stack_trace)
def test_init_empty_ticker_list(self): with self.assertRaises(ValidationError): PriceDispersionStrategy([], 2020, 2, 1)