def test_edge_case(self, dtype_device, use_rets, edge_case): dtype, device = dtype_device n_samples = 2 n_assets = 4 n_clusters = 1 if edge_case == 'single_cluster' else n_assets single_ = torch.rand(n_assets, n_assets, dtype=dtype, device=device) single = single_ @ single_.t() covmat = torch.stack([single for _ in range(n_samples)], dim=0) rets = torch.rand(n_samples, n_assets, dtype=dtype, device=device) if use_rets else None true_weights = AnalyticalMarkowitz()(covmat, rets=rets) pred_weights = NCO(n_clusters=n_clusters)(covmat, rets=rets) assert torch.allclose(pred_weights, true_weights, atol=1e-3) assert true_weights.device == pred_weights.device assert true_weights.dtype == pred_weights.dtype
def test_reproducible(self, dtype_device, use_rets): dtype, device = dtype_device n_samples = 2 n_assets = 6 n_clusters = 3 single_ = torch.rand(n_assets, n_assets, dtype=dtype, device=device) single = single_ @ single_.t() covmat = torch.stack([single for _ in range(n_samples)], dim=0) rets = torch.rand(n_samples, n_assets, dtype=dtype, device=device) if use_rets else None layer = NCO(n_clusters=n_clusters, random_state=2) weights_1 = layer(covmat, rets=rets) weights_2 = layer(covmat, rets=rets) assert torch.allclose(weights_1, weights_2) assert weights_1.device == weights_2.device assert weights_1.dtype == weights_2.dtype
def __init__( self, n_assets, max_weight=0.2, force_symmetric=False, n_clusters=5, n_init=100, init="random", random_state=None, ): 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 ) # torch.FloatTensor(n_assets).uniform_(-0.001, 0.001))#torch.tensor(exp_returns), requires_grad=True) #torch.zeros(n_assets), requires_grad=True) torch.nn.init.uniform_(self.exp_returns, a=-0.0005, b=0.0005) # self.gamma_sqrt = torch.nn.Parameter(torch.ones(1), requires_grad=True) # self.alpha = torch.nn.Parameter(torch.ones(1), requires_grad=True) # self.n_clusters = torch.nn.Parameter() # TODO: TRY TO IMPLEMENT THIS DIFFERENTIABLE. self.portfolio_opt_layer = NCO(n_clusters, n_init, init, random_state)