proof-of-portfolio 0.0.99__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 (23) 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 +98 -31
  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 +47 -14
  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 +3 -5
  16. proof_of_portfolio/circuits/target/circuits.json +1 -1
  17. proof_of_portfolio/circuits/vk/vk +0 -0
  18. proof_of_portfolio/proof_generator.py +5 -0
  19. {proof_of_portfolio-0.0.99.dist-info → proof_of_portfolio-0.0.101.dist-info}/METADATA +1 -1
  20. {proof_of_portfolio-0.0.99.dist-info → proof_of_portfolio-0.0.101.dist-info}/RECORD +23 -23
  21. {proof_of_portfolio-0.0.99.dist-info → proof_of_portfolio-0.0.101.dist-info}/WHEEL +0 -0
  22. {proof_of_portfolio-0.0.99.dist-info → proof_of_portfolio-0.0.101.dist-info}/entry_points.txt +0 -0
  23. {proof_of_portfolio-0.0.99.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,13 +10,14 @@ 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,
20
+ daily_rf: i64,
21
21
  ) -> i64 {
22
22
  if !bypass_confidence & actual_len < STATISTICAL_CONFIDENCE_MINIMUM_N {
23
23
  SORTINO_NOCONFIDENCE_VALUE
@@ -31,7 +31,7 @@ pub fn sortino(
31
31
 
32
32
  for i in 0..ARRAY_SIZE {
33
33
  if (i as u32) < actual_len {
34
- if log_returns[i] < DAILY_LOG_RISK_FREE_RATE {
34
+ if log_returns[i] < daily_rf {
35
35
  downside_returns_sum += log_returns[i];
36
36
  negative_count += 1;
37
37
  if use_weighting {
@@ -42,7 +42,7 @@ pub fn sortino(
42
42
  }
43
43
  }
44
44
 
45
- if negative_count > 1 {
45
+ if negative_count > 0 {
46
46
  let downside_mean = if use_weighting {
47
47
  if sum_w_down != 0 {
48
48
  weighted_sum_down / sum_w_down
@@ -57,9 +57,9 @@ pub fn sortino(
57
57
  let mut weighted_sum_sq_diff: i64 = 0;
58
58
  for i in 0..ARRAY_SIZE {
59
59
  if (i as u32) < actual_len {
60
- if log_returns[i] < DAILY_LOG_RISK_FREE_RATE {
60
+ if log_returns[i] < daily_rf {
61
61
  let diff = log_returns[i] - downside_mean;
62
- let sq_diff = (diff * diff) / 1000000;
62
+ let sq_diff = diff * diff;
63
63
  weighted_sum_sq_diff += sq_diff * weights[i];
64
64
  }
65
65
  }
@@ -73,9 +73,9 @@ pub fn sortino(
73
73
  let mut sum_sq_diff: i64 = 0;
74
74
  for i in 0..ARRAY_SIZE {
75
75
  if (i as u32) < actual_len {
76
- if log_returns[i] < DAILY_LOG_RISK_FREE_RATE {
76
+ if log_returns[i] < daily_rf {
77
77
  let diff = log_returns[i] - downside_mean;
78
- let sq_diff = (diff * diff) / 1000000;
78
+ let sq_diff = diff * diff;
79
79
  sum_sq_diff += sq_diff;
80
80
  }
81
81
  }
@@ -87,7 +87,7 @@ pub fn sortino(
87
87
  }
88
88
  };
89
89
 
90
- let annualized_variance = downside_variance_pre * (DAYS_IN_YEAR as i64) * 1000000;
90
+ let annualized_variance = downside_variance_pre * (DAYS_IN_YEAR as i64);
91
91
  let downside_volatility = sqrt(annualized_variance as u64) as i64;
92
92
 
93
93
  let effective_downside_volatility = if downside_volatility > SORTINO_DOWNSIDE_MINIMUM {
@@ -126,6 +126,7 @@ fn test_sortino_normal_case() {
126
126
  avg,
127
127
  variance_val,
128
128
  ann_excess,
129
+ 0,
129
130
  );
130
131
  assert(result != 0);
131
132
  }
@@ -151,8 +152,9 @@ fn test_sortino_no_negative_returns() {
151
152
  avg,
152
153
  variance_val,
153
154
  ann_excess,
155
+ 0,
154
156
  );
155
- assert(result == 0);
157
+ assert(result == SORTINO_NOCONFIDENCE_VALUE);
156
158
  }
157
159
 
158
160
  #[test]
@@ -176,6 +178,7 @@ fn test_sortino_all_negative_returns() {
176
178
  avg,
177
179
  variance_val,
178
180
  ann_excess,
181
+ 0,
179
182
  );
180
183
  assert(result != 0);
181
184
  }
@@ -203,6 +206,36 @@ fn test_sortino_high_downside_volatility() {
203
206
  avg,
204
207
  variance_val,
205
208
  ann_excess,
209
+ 0,
206
210
  );
207
211
  assert(result != 0);
208
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]
@@ -29,6 +29,7 @@ fn main(
29
29
  days_in_year: i64,
30
30
  omega_loss_min: i64,
31
31
  annual_risk_free: i64,
32
+ daily_rf: i64,
32
33
  drawdown_max_percent: i64,
33
34
  ) -> pub [Field; 9] {
34
35
  // Verify all trading signals are included in the merkle tree
@@ -119,13 +120,8 @@ fn main(
119
120
  let calmar_ratio = calmar(
120
121
  returns_array,
121
122
  n_returns,
122
- annual_risk_free,
123
- weights,
124
- use_weighting,
125
123
  bypass_confidence,
126
124
  avg_daily_return,
127
- variance_val,
128
- ann_excess_return_val,
129
125
  calmar_cap,
130
126
  days_in_year,
131
127
  drawdown_max_percent,
@@ -137,6 +133,7 @@ fn main(
137
133
  use_weighting,
138
134
  bypass_confidence,
139
135
  omega_loss_min,
136
+ daily_rf,
140
137
  );
141
138
  let sortino_ratio = sortino(
142
139
  returns_array,
@@ -148,6 +145,7 @@ fn main(
148
145
  avg_daily_return,
149
146
  variance_val,
150
147
  ann_excess_return_val,
148
+ daily_rf,
151
149
  );
152
150
  let stat_confidence = statistical_confidence(
153
151
  returns_array,