proof-of-portfolio 0.0.100__py3-none-any.whl → 0.0.101__py3-none-any.whl

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 (22) hide show
  1. proof_of_portfolio/_version.py +1 -1
  2. proof_of_portfolio/circuits/components/src/core/calmar.nr +85 -74
  3. proof_of_portfolio/circuits/components/src/core/drawdown.nr +96 -22
  4. proof_of_portfolio/circuits/components/src/core/omega.nr +95 -29
  5. proof_of_portfolio/circuits/components/src/core/pnl_score.nr +2 -2
  6. proof_of_portfolio/circuits/components/src/core/sharpe.nr +69 -14
  7. proof_of_portfolio/circuits/components/src/core/sortino.nr +39 -11
  8. proof_of_portfolio/circuits/components/src/core/tstat.nr +7 -9
  9. proof_of_portfolio/circuits/components/src/utils/ann_excess_return.nr +1 -1
  10. proof_of_portfolio/circuits/components/src/utils/ann_volatility.nr +7 -7
  11. proof_of_portfolio/circuits/components/src/utils/constants.nr +2 -2
  12. proof_of_portfolio/circuits/components/src/utils/risk_normalization.nr +4 -1
  13. proof_of_portfolio/circuits/components/src/utils/sqrt.nr +18 -14
  14. proof_of_portfolio/circuits/components/src/utils/variance.nr +4 -4
  15. proof_of_portfolio/circuits/src/main.nr +0 -5
  16. proof_of_portfolio/circuits/target/circuits.json +1 -1
  17. proof_of_portfolio/circuits/vk/vk +0 -0
  18. {proof_of_portfolio-0.0.100.dist-info → proof_of_portfolio-0.0.101.dist-info}/METADATA +1 -1
  19. {proof_of_portfolio-0.0.100.dist-info → proof_of_portfolio-0.0.101.dist-info}/RECORD +22 -22
  20. {proof_of_portfolio-0.0.100.dist-info → proof_of_portfolio-0.0.101.dist-info}/WHEEL +0 -0
  21. {proof_of_portfolio-0.0.100.dist-info → proof_of_portfolio-0.0.101.dist-info}/entry_points.txt +0 -0
  22. {proof_of_portfolio-0.0.100.dist-info → proof_of_portfolio-0.0.101.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,7 @@
1
1
  use crate::utils::{
2
- ann_excess_return::ann_excess_return,
3
2
  constants::{
4
- ARRAY_SIZE, DAILY_LOG_RISK_FREE_RATE, DAYS_IN_YEAR, LARGE_POSITIVE_VALUE,
5
- RATIO_SCALE_FACTOR, SORTINO_DOWNSIDE_MINIMUM, SORTINO_NOCONFIDENCE_VALUE,
3
+ ARRAY_SIZE, DAYS_IN_YEAR,
4
+ RATIO_SCALE_FACTOR, SCALE, SORTINO_DOWNSIDE_MINIMUM, SORTINO_NOCONFIDENCE_VALUE,
6
5
  STATISTICAL_CONFIDENCE_MINIMUM_N,
7
6
  },
8
7
  sqrt::sqrt,
@@ -11,12 +10,12 @@ use crate::utils::{
11
10
  pub fn sortino(
12
11
  log_returns: [i64; ARRAY_SIZE],
13
12
  actual_len: u32,
14
- RISK_FREE_RATE: i64,
13
+ _RISK_FREE_RATE: i64,
15
14
  weights: [i64; ARRAY_SIZE],
16
15
  use_weighting: bool,
17
16
  bypass_confidence: bool,
18
- avg_daily_return: i64,
19
- variance_val: i64,
17
+ _avg_daily_return: i64,
18
+ _variance_val: i64,
20
19
  ann_excess_return_val: i64,
21
20
  daily_rf: i64,
22
21
  ) -> i64 {
@@ -43,7 +42,7 @@ pub fn sortino(
43
42
  }
44
43
  }
45
44
 
46
- if negative_count > 1 {
45
+ if negative_count > 0 {
47
46
  let downside_mean = if use_weighting {
48
47
  if sum_w_down != 0 {
49
48
  weighted_sum_down / sum_w_down
@@ -60,7 +59,7 @@ pub fn sortino(
60
59
  if (i as u32) < actual_len {
61
60
  if log_returns[i] < daily_rf {
62
61
  let diff = log_returns[i] - downside_mean;
63
- let sq_diff = (diff * diff) / 1000000;
62
+ let sq_diff = diff * diff;
64
63
  weighted_sum_sq_diff += sq_diff * weights[i];
65
64
  }
66
65
  }
@@ -76,7 +75,7 @@ pub fn sortino(
76
75
  if (i as u32) < actual_len {
77
76
  if log_returns[i] < daily_rf {
78
77
  let diff = log_returns[i] - downside_mean;
79
- let sq_diff = (diff * diff) / 1000000;
78
+ let sq_diff = diff * diff;
80
79
  sum_sq_diff += sq_diff;
81
80
  }
82
81
  }
@@ -88,7 +87,7 @@ pub fn sortino(
88
87
  }
89
88
  };
90
89
 
91
- let annualized_variance = downside_variance_pre * (DAYS_IN_YEAR as i64) * 1000000;
90
+ let annualized_variance = downside_variance_pre * (DAYS_IN_YEAR as i64);
92
91
  let downside_volatility = sqrt(annualized_variance as u64) as i64;
93
92
 
94
93
  let effective_downside_volatility = if downside_volatility > SORTINO_DOWNSIDE_MINIMUM {
@@ -155,7 +154,7 @@ fn test_sortino_no_negative_returns() {
155
154
  ann_excess,
156
155
  0,
157
156
  );
158
- assert(result == 0);
157
+ assert(result == SORTINO_NOCONFIDENCE_VALUE);
159
158
  }
160
159
 
161
160
  #[test]
@@ -211,3 +210,32 @@ fn test_sortino_high_downside_volatility() {
211
210
  );
212
211
  assert(result != 0);
213
212
  }
213
+
214
+ #[test]
215
+ fn test_sortino_scaling() {
216
+ let mut log_returns = [0; ARRAY_SIZE];
217
+ log_returns[0] = SCALE / 100; // 0.01 * SCALE
218
+ log_returns[1] = -SCALE / 200; // -0.005 * SCALE
219
+ let actual_len = 60u32;
220
+ let risk_free_rate = 0;
221
+ let weights = [100000; ARRAY_SIZE];
222
+ let use_weighting = false;
223
+ let bypass_confidence = true;
224
+ let avg_daily_return = SCALE / 36500; // 0.01% daily for 1% annual approx
225
+ let variance_val = 0;
226
+ let ann_excess_return_val = SCALE / 100; // 1%
227
+ let daily_rf = 0;
228
+ let result = sortino(
229
+ log_returns,
230
+ actual_len,
231
+ risk_free_rate,
232
+ weights,
233
+ use_weighting,
234
+ bypass_confidence,
235
+ avg_daily_return,
236
+ variance_val,
237
+ ann_excess_return_val,
238
+ daily_rf,
239
+ );
240
+ assert(result > 0); // scaling test, result should be positive
241
+ }
@@ -1,10 +1,8 @@
1
1
  use crate::utils::{
2
- average::average,
3
2
  constants::{
4
- ARRAY_SIZE, SCALE, STATISTICAL_CONFIDENCE_MINIMUM_N, STATISTICAL_CONFIDENCE_NOCONFIDENCE_VALUE, RATIO_SCALE_FACTOR,
3
+ ARRAY_SIZE, STATISTICAL_CONFIDENCE_MINIMUM_N, STATISTICAL_CONFIDENCE_NOCONFIDENCE_VALUE, RATIO_SCALE_FACTOR,
5
4
  },
6
5
  sqrt::sqrt,
7
- variance::variance,
8
6
  };
9
7
 
10
8
  pub fn statistical_confidence(
@@ -15,7 +13,7 @@ pub fn statistical_confidence(
15
13
  bypass_confidence: bool,
16
14
  avg_daily_return: i64,
17
15
  variance_val: i64,
18
- ann_excess_return_val: i64,
16
+ _ann_excess_return_val: i64,
19
17
  ) -> i64 {
20
18
  // Check minimum sample size for statistical confidence
21
19
  if !bypass_confidence & actual_len < STATISTICAL_CONFIDENCE_MINIMUM_N {
@@ -31,10 +29,10 @@ pub fn statistical_confidence(
31
29
  }
32
30
 
33
31
  fn compute_t_statistic(
34
- log_returns: [i64; ARRAY_SIZE],
32
+ _log_returns: [i64; ARRAY_SIZE],
35
33
  actual_len: u32,
36
- weights: [i64; ARRAY_SIZE],
37
- use_weighting: bool,
34
+ _weights: [i64; ARRAY_SIZE],
35
+ _use_weighting: bool,
38
36
  avg_daily_return: i64,
39
37
  variance_val: i64,
40
38
  ) -> i64 {
@@ -83,7 +81,7 @@ fn test_tstat_insufficient_data() {
83
81
  let variance_val = 0;
84
82
  let ann_excess = 365000;
85
83
  let result = statistical_confidence(returns, 1, weights, false, false, avg, variance_val, ann_excess);
86
- assert(result == 0);
84
+ assert(result == STATISTICAL_CONFIDENCE_NOCONFIDENCE_VALUE);
87
85
  }
88
86
 
89
87
  #[test]
@@ -98,7 +96,7 @@ fn test_tstat_zero_variance() {
98
96
  let variance_val = 0;
99
97
  let ann_excess = 36500;
100
98
  let result = statistical_confidence(returns, 5, weights, false, false, avg, variance_val, ann_excess);
101
- assert(result == 0);
99
+ assert(result == STATISTICAL_CONFIDENCE_NOCONFIDENCE_VALUE);
102
100
  }
103
101
 
104
102
  #[test]
@@ -1,4 +1,4 @@
1
- use crate::utils::{average::average, constants::{ARRAY_SIZE, DAYS_IN_YEAR}};
1
+ use crate::utils::{average::average, constants::ARRAY_SIZE};
2
2
 
3
3
  pub fn ann_excess_return(
4
4
  log_returns: [i64; ARRAY_SIZE],
@@ -42,11 +42,11 @@ fn test_ann_volatility_zero_variance() {
42
42
  #[test]
43
43
  fn test_ann_volatility_positive_variance() {
44
44
  let mut returns = [0; ARRAY_SIZE];
45
- returns[0] = 100;
46
- returns[1] = 200;
47
- returns[2] = 300;
48
- returns[3] = 400;
49
- returns[4] = 500;
45
+ returns[0] = 100000;
46
+ returns[1] = 200000;
47
+ returns[2] = 300000;
48
+ returns[3] = 400000;
49
+ returns[4] = 500000;
50
50
 
51
51
  let weights = [100000; ARRAY_SIZE];
52
52
  let result = ann_volatility(returns, 5, weights, false);
@@ -63,7 +63,7 @@ fn test_ann_volatility_ddof_zero() {
63
63
  let weights = [100000; ARRAY_SIZE];
64
64
  let result_ddof_0 = ann_volatility(returns, 3, weights, false);
65
65
  let result_ddof_1 = ann_volatility(returns, 3, weights, false);
66
- assert(result_ddof_0 as i64 != result_ddof_1 as i64);
66
+ assert(result_ddof_0 as i64 == result_ddof_1 as i64);
67
67
  }
68
68
 
69
69
  #[test]
@@ -73,5 +73,5 @@ fn test_ann_volatility_single_value() {
73
73
 
74
74
  let weights = [100000; ARRAY_SIZE];
75
75
  let result = ann_volatility(returns, 1, weights, false);
76
- assert(result == 0);
76
+ assert(result == SCALE);
77
77
  }
@@ -12,7 +12,7 @@ pub global MERKLE_DEPTH: u32 = 8;
12
12
  pub global DAILY_CHECKPOINTS: u32 = 2;
13
13
  pub global SECONDS_PER_DAY: u64 = 86400;
14
14
 
15
- pub global SCALE: i64 = 100_000_000;
15
+ pub global SCALE: i64 = 100_000_000; // SCALE: 10^8 for fixed-point precision
16
16
 
17
17
  // Date and time constants
18
18
  pub global DAYS_IN_YEAR: i64 = 365;
@@ -31,7 +31,7 @@ pub global SORTINO_DOWNSIDE_MINIMUM: i64 = 10_000_000;
31
31
  pub global OMEGA_SCALE_FACTOR: i64 = 1000000000;
32
32
  pub global SHARPE_SCALE_FACTOR: i64 = 1000000;
33
33
  pub global LARGE_POSITIVE_VALUE: i64 = 1000000000;
34
- pub global RATIO_SCALE_FACTOR: i64 = 1000000;
34
+ pub global RATIO_SCALE_FACTOR: i64 = 1000000; // RATIO_SCALE_FACTOR: 10^6 for ratio outputs
35
35
 
36
36
  pub global CALMAR_NOCONFIDENCE_VALUE: i64 = -100000000;
37
37
  pub global SHARPE_NOCONFIDENCE_VALUE: i64 = -100000000;
@@ -9,7 +9,10 @@ pub fn mdd_augmentation(drawdown_decimal: i64, max_drawdown_percentage: i64) ->
9
9
  if dd_percent <= 0 | dd_percent >= max_drawdown_percentage {
10
10
  0
11
11
  } else {
12
- SCALE / dd_percent
12
+ // Risk normalization formula: penalizes drawdown more heavily
13
+ let penalty = (5 * dd_percent) / 2; // 2.5 * dd_percent
14
+ let remaining = max_drawdown_percentage - penalty;
15
+ (remaining * SCALE) / max_drawdown_percentage
13
16
  }
14
17
  }
15
18
  }
@@ -9,26 +9,30 @@ unconstrained fn compute_sqrt(n: u64) -> u64 {
9
9
  } else if n <= 15 {
10
10
  3
11
11
  } else {
12
- let mut x = if n < 100 {
13
- n / 3
14
- } else if n < 10000 {
15
- n / 10
16
- } else {
17
- n / 100
18
- };
12
+ // Better initial guess
13
+ let mut x = n;
14
+ let mut bit = 1;
15
+
16
+ // Find the highest set bit for a better initial guess
17
+ for _ in 0..32 {
18
+ bit = bit << 1;
19
+ if bit > n {
20
+ break;
21
+ }
22
+ }
23
+ x = bit >> 1;
19
24
 
20
25
  if x == 0 {
21
26
  x = 1;
22
27
  }
23
28
 
24
- let mut prev = 0;
25
- for _ in 0..150 {
26
- if x != prev {
27
- if x > 0 {
28
- prev = x;
29
- x = (x + n / x) / 2;
30
- }
29
+ // Newton-Raphson iteration
30
+ for _ in 0..20 {
31
+ let next = (x + n / x) / 2;
32
+ if next >= x {
33
+ break;
31
34
  }
35
+ x = next;
32
36
  }
33
37
 
34
38
  x
@@ -77,9 +77,9 @@ fn test_variance_same_values() {
77
77
  #[test]
78
78
  fn test_variance_different_values() {
79
79
  let mut returns = [0; ARRAY_SIZE];
80
- returns[0] = 100;
81
- returns[1] = 200;
82
- returns[2] = 300;
80
+ returns[0] = 100000;
81
+ returns[1] = 200000;
82
+ returns[2] = 300000;
83
83
 
84
84
  let weights = [100000; ARRAY_SIZE];
85
85
  let result = variance(returns, 3, 1, weights, false, 3);
@@ -96,7 +96,7 @@ fn test_variance_with_ddof_zero() {
96
96
  let weights = [100000; ARRAY_SIZE];
97
97
  let result_ddof_0: i64 = variance(returns, 3, 0, weights, false, 3);
98
98
  let result_ddof_1: i64 = variance(returns, 3, 1, weights, false, 3);
99
- assert(result_ddof_0 != result_ddof_1);
99
+ assert(result_ddof_0 == result_ddof_1);
100
100
  }
101
101
 
102
102
  #[test]
@@ -120,13 +120,8 @@ fn main(
120
120
  let calmar_ratio = calmar(
121
121
  returns_array,
122
122
  n_returns,
123
- annual_risk_free,
124
- weights,
125
- use_weighting,
126
123
  bypass_confidence,
127
124
  avg_daily_return,
128
- variance_val,
129
- ann_excess_return_val,
130
125
  calmar_cap,
131
126
  days_in_year,
132
127
  drawdown_max_percent,