docs: def _make_valid_bounds(self, test_bounds):
          """
          Private method: process input bounds into a form acceptable by scipy.optimize,
          and check the validity of said bounds.
  
          :param test_bounds: minimum and maximum weight of an asset
          :type test_bounds: tuple
          :raises ValueError: if ``test_bounds`` is not a tuple of length two.
          :raises ValueError: if the lower bound is too high
          :return: a tuple of bounds, e.g ((0, 1), (0, 1), (0, 1) ...)
          :rtype: tuple of tuples
          """
          if len(test_bounds) != 2 or not isinstance(test_bounds, tuple):
              raise ValueError(
                  "test_bounds must be a tuple of (lower bound, upper bound)"
              )
          if test_bounds[0] is not None:
              if test_bounds[0] * self.n_assets > 1:
                  raise ValueError("Lower bound is too high")
          return (test_bounds,) * self.n_assets