def display_results(self): ''' Displays the results of the strategy to the screen. Specifically displays the ranking of the securities using a Pandas Dataframe and the resulting recommendation set. ''' log.info("Calculating Current Returns") raw_dataframe = calculator.mark_to_market(self.raw_dataframe, 'ticker', 'analysis_price', self.current_price_date) recommendation_dataframe = calculator.mark_to_market( self.recommendation_dataframe, 'ticker', 'analysis_price', self.current_price_date) log.info("") log.info("Recommended Securities") log.info(util.format_dict(self.recommendation_set.to_dict())) log.info("") log.info("Recommended Securities Return: %.2f%%" % (recommendation_dataframe['actual_return'].mean() * 100)) log.info("Average Return: %.2f%%" % (raw_dataframe['actual_return'].mean() * 100)) log.info("") log.info("Analysis Period - %s, Actual Returns as of: %s" % (self.analysis_period, self.current_price_date)) # Using the logger will mess up the header of this table print(raw_dataframe[[ 'analysis_period', 'ticker', 'dispersion_stdev_pct', 'analyst_expected_return', 'actual_return', 'decile' ]].to_string(index=False))
def test_mark_to_market_price_exception(self): df_dict = {'ticker': ['a'], 'analysis_price': [10]} data_frame = pd.DataFrame(df_dict) with patch.object(intrinio_data, 'get_latest_close_price', side_effect=Exception("Not Found")): with self.assertRaises(DataError): calculator.mark_to_market(data_frame, datetime.now())
def test_mark_to_market_null_parameters(self): df_dict = { 'ticker': ['a', 'b', 'c', 'd'], 'analysis_price': [1, 2, 3, 4] } data_frame = pd.DataFrame(df_dict) with self.assertRaises(ValidationError): calculator.mark_to_market(data_frame, None) calculator.mark_to_market(None, datetime.now())
def test_mark_to_market_valid(self): df_dict = {'ticker': ['a'], 'analysis_price': [10]} data_frame = pd.DataFrame(df_dict) with patch.object(intrinio_data, 'get_latest_close_price', return_value=(datetime.now(), 20)): mmt_df = calculator.mark_to_market(data_frame, datetime.now()) self.assertEqual(mmt_df['current_price'][0], 20) self.assertEqual(mmt_df['actual_return'][0], 1.0)
def display_calculation_dataframe(month: int, year: int, strategy: object, current_price_date: datetime): ''' Displays the results of the calculation using a Pandas dataframe, using the supplied PriceDispersionStrategy object. Speficially display the underlining stock rankings that lead to the current recommendation ''' recommendation_set = strategy.recommendation_set recommendation_dataframe = strategy.recommendation_dataframe raw_dataframe = strategy.raw_dataframe log.info("Calculating Current Returns") raw_dataframe = calculator.mark_to_market(strategy.raw_dataframe, current_price_date) recommendation_dataframe = calculator.mark_to_market( strategy.recommendation_dataframe, current_price_date) log.info("") log.info("Recommended Securities") log.info(util.format_dict(recommendation_set.to_dict())) log.info("") log.info("Recommended Securities Return: %.2f%%" % (recommendation_dataframe['actual_return'].mean() * 100)) log.info("Average Return: %.2f%%" % (raw_dataframe['actual_return'].mean() * 100)) log.info("") log.info("Analysis Period - %d/%d, Actual Returns as of: %s" % (month, year, datetime.strftime(current_price_date, '%Y/%m/%d'))) # Using the logger will mess up the header of this table print(raw_dataframe[[ 'analysis_period', 'ticker', 'dispersion_stdev_pct', 'analyst_expected_return', 'actual_return', 'decile' ]].to_string(index=False))
def test_mark_to_market_valid(self): df_dict = {'ticker': ['a'], 'analysis_price': [10]} data_frame = pd.DataFrame(df_dict) with patch.object(intrinio_data, 'get_daily_stock_close_prices', return_value=({ '2020-10-22': 20 })): mmt_df = calculator.mark_to_market(data_frame, 'ticker', 'analysis_price', date(2020, 10, 22)) self.assertEqual(mmt_df['current_price'][0], 20) self.assertEqual(mmt_df['actual_return'][0], 1.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_mark_to_market_df_invalid_columns(self): df_dict = {'a': ['a', 'b', 'c', 'd'], 'b': [1, 2, 3, 4]} data_frame = pd.DataFrame(df_dict) with self.assertRaises(ValidationError): calculator.mark_to_market(data_frame, datetime.now())
def test_mark_to_market_df_invalid_columns(self): df_dict = {'a': ['a', 'b', 'c', 'd'], 'b': [1, 2, 3, 4]} data_frame = pd.DataFrame(df_dict) with self.assertRaises(ValidationError): calculator.mark_to_market(data_frame, 'ticker', 'analysis_price', date.today())