Exemple #1
0
    def test_basic(self, Xy_dummy, formulation):
        eps = 1e-5
        X, _, _, _ = Xy_dummy
        dtype, device = X.dtype, X.device
        n_samples, n_channels, lookback, n_assets = X.shape

        rets = X.mean(dim=(1, 2))

        with pytest.raises(ValueError):
            SoftmaxAllocator(temperature=None,
                             formulation=formulation,
                             n_assets=n_assets)(rets, temperature=None)

        weights = SoftmaxAllocator(temperature=2,
                                   formulation=formulation,
                                   n_assets=n_assets)(rets)

        assert torch.allclose(
            weights,
            SoftmaxAllocator(
                temperature=None, formulation=formulation, n_assets=n_assets)(
                    rets,
                    2 * torch.ones(n_samples, dtype=dtype, device=device)))
        assert weights.shape == (n_samples, n_assets)
        assert weights.dtype == X.dtype
        assert weights.device == X.device
        assert torch.all(-eps <= weights) and torch.all(weights <= 1 + eps)
        assert torch.allclose(weights.sum(dim=1),
                              torch.ones(n_samples).to(dtype=dtype,
                                                       device=device),
                              atol=eps)
Exemple #2
0
    def test_errors(self):
        with pytest.raises(ValueError):
            SoftmaxAllocator(formulation='wrong')

        with pytest.raises(ValueError):
            SoftmaxAllocator(formulation='variational', n_assets=None)

        with pytest.raises(ValueError):
            SoftmaxAllocator(formulation='analytical', max_weight=0.3)

        with pytest.raises(ValueError):
            SoftmaxAllocator(formulation='variational', max_weight=0.09, n_assets=10)
Exemple #3
0
    def test_contstrained(self, max_weight):
        rets = torch.tensor([[1.7909, -2, -0.6818, -0.4972, 0.0333]])

        w_const = SoftmaxAllocator(n_assets=5,
                                   temperature=1,
                                   max_weight=max_weight,
                                   formulation='variational')(rets)
        w_unconst = SoftmaxAllocator(n_assets=5,
                                     temperature=1,
                                     max_weight=1,
                                     formulation='variational')(rets)

        assert not torch.allclose(w_const, w_unconst)
        assert w_const.max().item() == pytest.approx(max_weight, abs=1e-4)
Exemple #4
0
    def test_uniform(self, formulation):
        rets = torch.ones(2, 5)
        weights = SoftmaxAllocator(formulation=formulation,
                                   n_assets=5,
                                   temperature=1)(rets)

        assert torch.allclose(weights, rets / 5, atol=1e-4)
Exemple #5
0
    def __init__(self, n_assets, lookback, p=0.5):
        super().__init__()

        n_features = n_assets * lookback

        self.dropout_layer = torch.nn.Dropout(p=p)
        self.dense_layer = torch.nn.Linear(n_features, n_assets, bias=True)
        self.allocate_layer = SoftmaxAllocator(temperature=None)
        self.temperature = torch.nn.Parameter(torch.ones(1),
                                              requires_grad=True)
Exemple #6
0
    def test_equality_formulations(self, dtype_device):
        dtype, device = dtype_device
        n_samples, n_assets = 3, 6

        layer_analytical = SoftmaxAllocator(formulation='analytical')
        layer_variational = SoftmaxAllocator(formulation='variational', n_assets=n_assets)

        torch.manual_seed(2)
        rets = torch.randint(10, size=(n_samples, n_assets)) + torch.rand(size=(n_samples, n_assets))
        rets = rets.to(device=device, dtype=dtype)

        weights_analytical = layer_analytical(rets)
        weights_variational = layer_variational(rets)

        assert weights_analytical.shape == weights_variational.shape
        assert weights_analytical.dtype == weights_variational.dtype
        assert weights_analytical.device == weights_variational.device

        assert torch.allclose(weights_analytical, weights_variational, atol=1e-4)
Exemple #7
0
 def __init__(
     self,
     n_assets,
     max_weight=0.2,
     force_symmetric=True,
 ):
     super().__init__()
     self.force_symmetric = force_symmetric
     self.matrix = torch.nn.Parameter(torch.eye(n_assets),
                                      requires_grad=True)
     self.exp_returns = torch.nn.Parameter(torch.zeros(n_assets),
                                           requires_grad=True)
     self.temperature = torch.nn.Parameter(torch.ones(1),
                                           requires_grad=True)
     self.gamma_sqrt = torch.nn.Parameter(torch.ones(1), requires_grad=True)
     self.alpha = torch.nn.Parameter(torch.ones(1), requires_grad=True)
     self.pre_alloc_layer = NumericalMarkowitz(n_assets, max_weight)
     self.allocation_layer = SoftmaxAllocator(
         n_assets=n_assets,
         temperature=None,
         max_weight=max_weight,
         formulation="variational",
     )
Exemple #8
0
fig, axs = plt.subplots(len(temperatures),
                        len(max_weights),
                        sharex=True,
                        sharey=True,
                        figsize=(15, 5))
cbar_ax = fig.add_axes([.91, .3, .03, .4])

for r, temperature in enumerate(temperatures):
    for c, max_weight in enumerate(max_weights):
        sparsemax = SparsemaxAllocator(n_assets,
                                       max_weight=max_weight,
                                       temperature=temperature)

        softmax = SoftmaxAllocator(n_assets=n_assets,
                                   temperature=temperature,
                                   max_weight=max_weight,
                                   formulation='variational')

        w_sparsemax = sparsemax(logits).detach().numpy()
        w_softmax = softmax(logits).detach().numpy()

        df = pd.DataFrame(np.concatenate([w_softmax, w_sparsemax], axis=0),
                          index=['softmax', 'sparsemax'])

        axs[r, c].set_title('temp={}, max_weight={}'.format(
            temperature, max_weight))
        sns.heatmap(df,
                    vmin=0,
                    vmax=1,
                    center=0.5,
                    cmap='hot',