numerai-tools 0.5.1__tar.gz → 0.5.2.dev1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: numerai-tools
3
- Version: 0.5.1
3
+ Version: 0.5.2.dev1
4
4
  Summary: A collection of open-source tools to help interact with Numerai, model data, and automate submissions.
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -614,12 +614,14 @@ def meta_portfolio_contribution(
614
614
  sample_weights: pd.Series,
615
615
  targets: pd.Series,
616
616
  ) -> pd.Series:
617
- """Calculates the "meta portfolio" score:
618
- - rank, normalize, and power each signal
619
- - convert each signal into neutralized weights
620
- - generate the stake-weighted portfolio
621
- - calculate the gradient of the portfolio w.r.t. the stakes
622
- - multiplying the weights by the targets
617
+ """Calculates the "meta portfolio" gradient w.r.t. stakes:
618
+ - rank, normalize, and power each signal
619
+ - convert each signal into neutralized weights
620
+ - center weights across samples (explicit W_c = C W)
621
+ - generate the stake-weighted portfolio
622
+ - calculate the gradient of the portfolio w.r.t. the stakes
623
+ - multiply by the (centered) targets
624
+
623
625
  Arguments:
624
626
  predictions: pd.DataFrame - the predictions to evaluate
625
627
  stakes: pd.Series - the stakes to use as weights
@@ -627,22 +629,41 @@ def meta_portfolio_contribution(
627
629
  sample_weights: pd.Series - the universe sampling weights
628
630
  targets: pd.Series - the live targets to evaluate against
629
631
  """
630
- targets = center(targets)
632
+ # Align predictions and targets on the same index / universe
631
633
  predictions, targets = filter_sort_index(predictions, targets)
634
+
635
+ # Center targets in sample space: t_c = C t
636
+ targets = center(targets)
637
+
638
+ # Normalize stakes to sum to 1
632
639
  stake_weights = weight_normalize(stakes.fillna(0))
633
640
  assert np.isclose(stake_weights.sum(), 1), "Stakes must sum to 1"
641
+
642
+ # Generate neutralized weights W(predictions, neutralizers, sample_weights)
634
643
  weights = generate_neutralized_weights(predictions, neutralizers, sample_weights)
635
- w = cast(np.ndarray, weights[stakes.index].values)
636
- s = cast(np.ndarray, stake_weights.values)
637
- t = cast(np.ndarray, targets.values)
638
- swp = w @ s
639
- swp = swp - swp.mean()
640
- l1_norm = np.sum(np.abs(swp))
641
- l1_norm_squared = np.power(l1_norm, 2)
642
- swp_sign = np.sign(swp)
643
- swp_alpha = np.dot(swp, t)
644
- directional_gradient = l1_norm * t - swp_sign * swp_alpha
645
- jacobian_vector_product = directional_gradient.reshape(-1, 1) / l1_norm_squared
646
- centered_jacobian = jacobian_vector_product - jacobian_vector_product.mean()
647
- mpc = (w.T @ centered_jacobian).squeeze()
644
+
645
+ # Extract aligned matrices/vectors
646
+ w = cast(np.ndarray, weights[stakes.index].values) # W ∈ R^{N×K}
647
+ s = cast(np.ndarray, stake_weights.values) # s ∈ R^K
648
+ t = cast(np.ndarray, targets.values) # t_c ∈ R^N (already centered)
649
+
650
+ # Explicit centering of weights across samples:
651
+ # W_c = C W = W - 1 μ^T, where μ is the column-wise mean of W
652
+ w_centered = w - w.mean(axis=0, keepdims=True) # W_c
653
+
654
+ # Centered prediction vector v = W_c s
655
+ v = w_centered @ s # v ∈ R^N, already mean ~ 0
656
+ # Optionally re-center to remove numerical drift
657
+ v = v - v.mean()
658
+
659
+ # Its L2 norm r = ||v||
660
+ l2_norm = np.sqrt(np.sum(v**2))
661
+
662
+ # Residualize W_c against v:
663
+ # residualized_w ≈ R_v W_c = (I - v v^T / ||v||^2) W_c
664
+ residualized_w = orthogonalize(w_centered, v)
665
+
666
+ # Gradient: ∇_s α = (1 / ||v||) (R_v W_c)^T t_c
667
+ mpc = (residualized_w.T @ t).squeeze() / l2_norm
668
+
648
669
  return pd.Series(mpc, index=stakes.index)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "numerai-tools"
3
- version = "0.5.1"
3
+ version = "0.5.2.dev1"
4
4
  description = "A collection of open-source tools to help interact with Numerai, model data, and automate submissions."
5
5
  authors = [
6
6
  {name = "Numerai Engineering",email = "engineering@numer.ai"}