numerai-tools 0.4.0.dev2__tar.gz → 0.4.2.dev0__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.
Files changed (18) hide show
  1. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/PKG-INFO +1 -1
  2. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/numerai_tools/scoring.py +18 -12
  3. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/numerai_tools/signals.py +28 -1
  4. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/numerai_tools.egg-info/PKG-INFO +1 -1
  5. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/numerai_tools.egg-info/requires.txt +0 -1
  6. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/setup.py +1 -2
  7. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/tests/test_scoring.py +2 -2
  8. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/tests/test_signals.py +8 -1
  9. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/LICENSE +0 -0
  10. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/README.md +0 -0
  11. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/numerai_tools/__init__.py +0 -0
  12. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/numerai_tools/py.typed +0 -0
  13. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/numerai_tools/submissions.py +0 -0
  14. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/numerai_tools.egg-info/SOURCES.txt +0 -0
  15. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/numerai_tools.egg-info/dependency_links.txt +0 -0
  16. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/numerai_tools.egg-info/top_level.txt +0 -0
  17. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/setup.cfg +0 -0
  18. {numerai_tools-0.4.0.dev2 → numerai_tools-0.4.2.dev0}/tests/test_submissions.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: numerai_tools
3
- Version: 0.4.0.dev2
3
+ Version: 0.4.2.dev0
4
4
  Summary: A collection of open-source tools to help interact with Numerai, model data, and automate submissions.
5
5
  Home-page: https://github.com/numerai/numerai-tools
6
6
  Maintainer: Numerai
@@ -582,10 +582,11 @@ def meta_portfolio_contribution(
582
582
  targets: pd.Series,
583
583
  ) -> pd.Series:
584
584
  """Calculates the "meta portfolio" score:
585
- - rank, normalize, and power the signal
586
- - convert signal into neutralized weights
585
+ - rank, normalize, and power each signal
586
+ - convert each signal into neutralized weights
587
+ - generate the stake-weighted portfolio
588
+ - calculate the gradient of the portfolio w.r.t. the stakes
587
589
  - multiplying the weights by the targets
588
-
589
590
  Arguments:
590
591
  predictions: pd.DataFrame - the predictions to evaluate
591
592
  stakes: pd.Series - the stakes to use as weights
@@ -599,22 +600,27 @@ def meta_portfolio_contribution(
599
600
  predictions, neutralizers, sample_weights, targets = filter_sort_index_many(
600
601
  [predictions, neutralizers, sample_weights, targets]
601
602
  )
602
-
603
603
  stake_weights = weight_normalize(stakes.fillna(0))
604
604
  assert np.isclose(stake_weights.sum(), 1), "Stakes must sum to 1"
605
-
606
605
  weights = tie_kept_rank__gaussianize__pow_1_5(predictions).apply(
607
606
  lambda s_prime: generate_neutralized_weights(
608
607
  s_prime, neutralizers, sample_weights
609
608
  )
610
609
  )
611
-
612
- w = torch.tensor(weights[stakes.index].values)
613
- s = torch.tensor(stake_weights.values, requires_grad=True)
614
- t = torch.tensor(targets.values)
610
+ w = weights[stakes.index].values
611
+ s = stake_weights.values
612
+ t = targets.values
615
613
  swp = w @ s
616
614
  swp = swp - swp.mean()
617
- swp = swp / swp.abs().sum()
618
- alpha = swp @ t
619
- mpc = torch.autograd.grad(alpha, s)[0].numpy()
615
+ swp_abs_sum = np.sum(np.abs(swp))
616
+ swp_sign = np.sign(swp)
617
+ alpha_unnormalized_swp_grad = (
618
+ 1
619
+ / np.power(swp_abs_sum, 2)
620
+ * (swp_abs_sum * t - swp_sign * np.dot(swp, t)).reshape(-1, 1)
621
+ )
622
+ zero_mean_jac_vec_prod = (
623
+ alpha_unnormalized_swp_grad - alpha_unnormalized_swp_grad.mean()
624
+ )
625
+ mpc = (w.T @ zero_mean_jac_vec_prod).squeeze()
620
626
  return pd.Series(mpc, index=stakes.index)
@@ -19,7 +19,8 @@ def churn(
19
19
 
20
20
  For 2 given series with overlapping indices, churn is 1 - Spearman Correlation.
21
21
  If top_bottom is provided, the churn is calculated as the average of the % of
22
- tickers that stay in the top and bottom predictions.
22
+ tickers that stay in the top and bottom predictions. This is only relevant when
23
+ the series are rank signals and not portfolio weights.
23
24
 
24
25
  Arguments:
25
26
  s1: pd.Series - the first series to compare
@@ -43,3 +44,29 @@ def churn(
43
44
  assert s1.std() > 0, "s1 must have non-zero standard deviation"
44
45
  assert s2.std() > 0, "s2 must have non-zero standard deviation"
45
46
  return 1 - spearman_correlation(s1, s2)
47
+
48
+
49
+ def turnover(
50
+ s1: pd.Series,
51
+ s2: pd.Series,
52
+ ):
53
+ """Calculate the turnover between two series. Turnover is the total change in weights between
54
+ the two series divided by 2.
55
+
56
+ For 2 given series with overlapping indices, join the series on index, fill nans with zeroes
57
+ and calculate turnover as the absolute total difference between the two series divided by 2.
58
+ This is only relevant when the series are portfolio weights and not rank signals.
59
+
60
+ Arguments:
61
+ s1: pd.Series - the first series to compare
62
+ s2: pd.Series - the second series to compare
63
+ top_bottom: Optional[int] - the number of top and bottom predictions to use
64
+ when calculating the correlation. Results in
65
+ 2*top_bottom predictions.
66
+
67
+ Returns:
68
+ float - the turnover between the two series
69
+ """
70
+ s1, s2 = filter_sort_index(s1, s2)
71
+ turnover = (s1 - s2).abs().sum() / 2
72
+ return turnover
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: numerai-tools
3
- Version: 0.4.0.dev2
3
+ Version: 0.4.2.dev0
4
4
  Summary: A collection of open-source tools to help interact with Numerai, model data, and automate submissions.
5
5
  Home-page: https://github.com/numerai/numerai-tools
6
6
  Maintainer: Numerai
@@ -2,4 +2,3 @@ pandas<3.0.0,>=2.2.2
2
2
  numpy<3.0.0,>=2.0.0
3
3
  scipy<2.0.0,>=1.13.0
4
4
  scikit-learn<2.0.0,>=1.5.0
5
- torch
@@ -1,7 +1,7 @@
1
1
  from setuptools import setup
2
2
  from setuptools import find_packages
3
3
 
4
- VERSION = "0.4.0.dev2"
4
+ VERSION = "0.4.2.dev0"
5
5
 
6
6
 
7
7
  def load(path):
@@ -43,6 +43,5 @@ if __name__ == "__main__":
43
43
  "numpy>=2.0.0,<3.0.0",
44
44
  "scipy>=1.13.0,<2.0.0",
45
45
  "scikit-learn>=1.5.0,<2.0.0",
46
- "torch",
47
46
  ],
48
47
  )
@@ -318,8 +318,8 @@ class TestScoring(unittest.TestCase):
318
318
  [5, 1],
319
319
  ]
320
320
  )
321
- v = pd.Series([3, 2, 1, 2, 3]).T
322
- t = pd.Series([1, 2, 3, 2, 1]).T
321
+ v = pd.Series([1, 0.5, 1, 0.5, 1]).T
322
+ t = pd.Series([1, 0, 1, 0, 1]).T
323
323
  score = alpha(s, N, v, t)
324
324
  np.testing.assert_allclose(score, 0.0, atol=1e-14, rtol=1e-14)
325
325
 
@@ -3,7 +3,7 @@ import unittest
3
3
  import numpy as np
4
4
  import pandas as pd # type: ignore
5
5
 
6
- from numerai_tools.signals import churn
6
+ from numerai_tools.signals import churn, turnover
7
7
 
8
8
 
9
9
  class TestSignals(unittest.TestCase):
@@ -39,6 +39,13 @@ class TestSignals(unittest.TestCase):
39
39
  tmp = churn(self.up, self.constant, top_bottom=2)
40
40
  assert np.isclose(tmp, 0), tmp
41
41
 
42
+ def test_turnover(self):
43
+ assert np.isclose(turnover(self.up, self.up), 0)
44
+ assert np.isclose(turnover(self.up, self.up_down), 3)
45
+ assert np.isclose(turnover(self.up, self.oscillate), 4.5)
46
+ assert np.isclose(turnover(self.up, self.down), 6)
47
+ assert np.isclose(turnover(self.up, self.constant), 3.5)
48
+
42
49
 
43
50
  if __name__ == "__main__":
44
51
  unittest.main()