def test_short_returns(): b_data = prep_data.get_data('^GSPC', '2018-05-01', '2019-05-01', 'monthly') b_transformed_data, dates = prep_data.transform_yahoo_finance_dict(b_data) b_asset_data = prep_data.generate_asset_data_array(b_transformed_data) # MSFT is a winner, X is a loser during this period data = prep_data.get_data(['MSFT', 'X'], '2018-05-01', '2019-05-01', 'monthly') transformed_data, dates = prep_data.transform_yahoo_finance_dict(data) asset_data = prep_data.generate_asset_data_array(transformed_data) msft_start = asset_data[0].price_data[-1] msft_end = asset_data[0].price_data[0] msft_ret = (msft_end - msft_start) / msft_start x_start = asset_data[1].price_data[-1] x_end = asset_data[1].price_data[0] x_ret = (x_end - x_start) / x_start # Calculate long only returns long_p_ret = PortfolioReturns(asset_data, np.array([0.5, 0.5]), b_asset_data[0]) expected_return = (msft_ret + x_ret) / 2 assert round(long_p_ret.total_return, 3) == round(expected_return, 3) # Calculate long / short returns long_short_p_ret = PortfolioReturns(asset_data, np.array([0.5, -0.5]), b_asset_data[0]) expected_return = (msft_ret - x_ret) / 2 assert round(long_short_p_ret.total_return, 3) == round(expected_return, 3)
def do_task_optimize(name, tickers, benchmark_index: str, start_date, end_date, user_id, task_id, interval='weekly'): job_start = datetime.now() # Get & prepare portfolio data data = prep_data.get_data(tickers, start_date, end_date, interval) transformed_data, dates = prep_data.transform_yahoo_finance_dict(data) asset_data = prep_data.generate_asset_data_array(transformed_data) # Get benchmark data benchmark_data = prep_data.get_data(benchmark_index, start_date, end_date, interval) benchmark_transformed_data, _ = prep_data.transform_yahoo_finance_dict( benchmark_data) benchmark_asset_data = prep_data.generate_asset_data_array( benchmark_transformed_data) benchmark_returns = PortfolioReturns(benchmark_asset_data) # Optimize portfolio matrices = prep_data.AssetMatrices(asset_data) optimizer = optimize.Optimize(matrices, benchmark_asset_data[0]) results = optimizer.optimize_all() job_end = datetime.now() job = { 'job_start': job_start, 'job_end': job_end, 'asset_data': [a.as_dict() for a in asset_data], 'matrices': matrices.as_dict(), 'price_dates': dates, 'parameters': { 'tickers': tickers, 'start_date': start_date, 'end_date': end_date, 'interval': interval }, 'benchmark_index': { 'asset_data': benchmark_asset_data[0].as_dict(), 'returns': benchmark_returns.as_dict() }, 'results': [res.as_dict() for res in results], 'user_id': user_id, 'task_id': task_id, 'published': False, 'name': name } return insert_job(job)
def test_short_returns_complex(): b_data = prep_data.get_data('^GSPC', '2018-05-13', '2019-05-13', 'weekly') b_transformed_data, dates = prep_data.transform_yahoo_finance_dict(b_data) b_asset_data = prep_data.generate_asset_data_array(b_transformed_data) data = prep_data.get_data(['MSFT', 'X', 'AA', 'SPLK'], '2018-05-13', '2019-05-13', 'weekly') transformed_data, dates = prep_data.transform_yahoo_finance_dict(data) asset_data = prep_data.generate_asset_data_array(transformed_data) long_p_ret = PortfolioReturns(asset_data, np.array([1., 0., 0., 0.]), b_asset_data[0]) long_short_p_ret = PortfolioReturns( asset_data, np.array([1., -0.3847, -0.3808, 0.7655]), b_asset_data[0]) assert 1 == 1
def generate_min_std_dev(self, shorting_allowed=False) -> OptimizeOutcome: def min_std_dev_fn(weights_vec: np.ndarray): return self.calculate_std_dev( weights_vec, self.asset_matrices.variance_covariance_matrix) bnds = self.short_ok_bnds if shorting_allowed else self.long_only_bnds optimize_result: OptimizeResult = minimize( min_std_dev_fn, self.equal_weights, method='SLSQP', bounds=bnds, constraints=[ self.weights_equal_1_constraint, self.returns_gte_max_constraint ]) pw = self.process_weights(optimize_result.x) portfolio_returns = PortfolioReturns(self.asset_matrices.asset_data, pw['normalized_weights'], self.benchmark_data) return OptimizeOutcome(OptimizeGoal.MIN_STD_DEV, shorting_allowed, pw['normalized_weights'], pw['returns'], pw['std_dev'], pw['sharpe_ratio'], optimize_result, portfolio_returns)
def test_returns_s_and_p_500(): data = prep_data.get_data('^GSPC', '2018-05-01', '2019-02-01', 'weekly') transformed_data, dates = prep_data.transform_yahoo_finance_dict(data) asset_data = prep_data.generate_asset_data_array(transformed_data) portfolio_returns = PortfolioReturns(asset_data) assert len(portfolio_returns.portfolio_returns) == len( asset_data[0].returns) assert len(portfolio_returns.portfolio_values) == len( asset_data[0].price_data)
def __init__(self, asset_matrices: AssetMatrices, benchmark_data: AssetData): self.asset_matrices = asset_matrices self.benchmark_data = benchmark_data # Bounds for optimizer must match length of data self.long_only_bnds = [[0, 1] for x in asset_matrices.asset_data] self.short_ok_bnds = [[-1, 1] for x in asset_matrices.asset_data] # Generate equal returns data as a baseline self.equal_weights = np.array([1 / len(asset_matrices.asset_data)] * len(asset_matrices.asset_data)) equal_weights_results = self.process_weights(self.equal_weights) equal_weights_returns = PortfolioReturns( self.asset_matrices.asset_data, self.equal_weights, benchmark_data) self.equal_weights_outcome = OptimizeOutcome( OptimizeGoal.EQUAL_WEIGHT, False, self.equal_weights, equal_weights_results['returns'], equal_weights_results['std_dev'], equal_weights_results['sharpe_ratio'], None, equal_weights_returns) self.min_std_dev = np.min(asset_matrices.std_dev_vec) # The standard deviation must be <= the lowest standard deviation of any assets self.std_dev_lte_min_constraint = { 'type': 'ineq', 'fun': lambda arr: self.min_std_dev - self.calculate_std_dev( arr, self.asset_matrices.variance_covariance_matrix) } self.max_returns = np.max(asset_matrices.avg_returns_vec) # The rate of return must be greater than the rate of return for any asset self.returns_gte_max_constraint = { 'type': 'ineq', 'fun': lambda arr: self.calculate_returns( arr, self.asset_matrices.avg_returns_vec) - self.max_returns }