示例#1
0
    def test_sample_independence(self, input_type, output_type, rebalance):
        y_a = torch.tensor([[0.01, 0.02],
                            [-0.05, 0.04]])  # assets move in a different way
        y_b = torch.tensor([[0.01, 0.03],
                            [-0.01, -0.02]])  # assets move in the same way
        w_a = torch.tensor([0.2, 0.8])
        w_b = torch.tensor([0.45, 0.55])

        w_1 = torch.stack([w_a, w_b], dim=0)
        y_1 = torch.stack([y_a, y_b], dim=0)
        w_2 = torch.stack([w_b, w_a], dim=0)
        y_2 = torch.stack([y_b, y_a], dim=0)

        res_1 = portfolio_returns(w_1,
                                  y_1,
                                  input_type=input_type,
                                  output_type=output_type,
                                  rebalance=rebalance)
        res_2 = portfolio_returns(w_2,
                                  y_2,
                                  input_type=input_type,
                                  output_type=output_type,
                                  rebalance=rebalance)

        assert torch.allclose(res_1[0], res_2[1])
        assert torch.allclose(res_1[1], res_2[0])
示例#2
0
    def test_errors(self):
        n_samples = 3
        n_assets = 2
        horizon = 4

        weights = torch.ones((n_samples, n_assets))
        y = torch.ones((n_samples, horizon, n_assets))

        with pytest.raises(ValueError):
            portfolio_returns(weights, y, input_type='fake')

        with pytest.raises(ValueError):
            portfolio_returns(weights, y, output_type='fake')
示例#3
0
    def test_shape(self, Xy_dummy, input_type, output_type):
        _, y_dummy, _, _ = Xy_dummy
        y_dummy = y_dummy[:, 0, ...]
        n_samples, horizon, n_assets = y_dummy.shape

        weights = torch.randint(1, 10, size=(n_samples, n_assets)).to(device=y_dummy.device, dtype=y_dummy.dtype)
        weights = weights / weights.sum(-1, keepdim=True)

        prets = portfolio_returns(weights, y_dummy, input_type=input_type, output_type=output_type)

        assert prets.shape == (n_samples, horizon)
示例#4
0
    def test_sanity_check(self, input_type):
        initial_wealth = 50
        y_1_ = torch.tensor([[0.01, 0.02],
                             [-0.05, 0.04]])  # assets move in a different way
        y_2_ = torch.tensor([[0.01, 0.01],
                             [-0.05, -0.05]])  # assets move in the same way

        w_a_ = torch.tensor([0.2, 0.8])

        y_1 = y_1_[None, ...]
        y_2 = y_2_[None, ...]
        w_a = w_a_[None, ...]

        # No need to rebalance when returns evolve in the same way
        assert torch.allclose(portfolio_returns(w_a,
                                                y_2,
                                                rebalance=True,
                                                input_type=input_type),
                              portfolio_returns(w_a,
                                                y_2,
                                                rebalance=False,
                                                input_type=input_type))

        # rebalancing necessary when returns evolve differently
        assert not torch.allclose(portfolio_returns(w_a, y_1, rebalance=True, input_type=input_type),
                                  portfolio_returns(w_a, y_1, rebalance=False, input_type=input_type))

        # manually computed returns

        if input_type == 'simple':
            h_per_asset_1 = torch.tensor([[w_a_[0], w_a_[1]],
                                          [w_a_[0] * (1 + y_1_[0, 0]), w_a_[1] * (1 + y_1_[0, 1])],
                                          [w_a_[0] * (1 + y_1_[0, 0]) * (1 + y_1_[1, 0]),
                                           w_a_[1] * (1 + y_1_[0, 1]) * (1 + y_1_[1, 1])]
                                          ]) * initial_wealth
        else:
            h_per_asset_1 = torch.tensor([[w_a_[0], w_a_[1]],
                                          [w_a_[0] * torch.exp(y_1_[0, 0]), w_a_[1] * torch.exp(y_1_[0, 1])],
                                          [w_a_[0] * torch.exp(y_1_[0, 0]) * torch.exp(y_1_[1, 0]),
                                           w_a_[1] * torch.exp(y_1_[0, 1]) * torch.exp(y_1_[1, 1])]
                                          ]) * initial_wealth

        h_1 = h_per_asset_1.sum(1)

        correct_simple_returns = torch.tensor([(h_1[1] / h_1[0]) - 1, (h_1[2] / h_1[1]) - 1])
        correct_log_returns = torch.tensor([torch.log(h_1[1] / h_1[0]), torch.log(h_1[2] / h_1[1])])
        correct_simple_creturns = torch.tensor([(h_1[1] / h_1[0]) - 1, (h_1[2] / h_1[0]) - 1])
        correct_log_creturns = torch.tensor([torch.log(h_1[1] / h_1[0]), torch.log(h_1[2] / h_1[0])])

        assert torch.allclose(portfolio_returns(w_a,
                                                y_1,
                                                input_type=input_type,
                                                output_type='simple',
                                                rebalance=False)[0],
                              correct_simple_returns)

        assert torch.allclose(portfolio_returns(w_a,
                                                y_1,
                                                input_type=input_type,
                                                output_type='log',
                                                rebalance=False)[0],
                              correct_log_returns)

        assert torch.allclose(portfolio_cumulative_returns(w_a,
                                                           y_1,
                                                           input_type=input_type,
                                                           output_type='simple',
                                                           rebalance=False)[0],
                              correct_simple_creturns)

        assert torch.allclose(portfolio_cumulative_returns(w_a,
                                                           y_1,
                                                           input_type=input_type,
                                                           output_type='log',
                                                           rebalance=False)[0],
                              correct_log_creturns)