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,2 +1,2 @@
1
1
  # This file is auto-generated during build
2
- __version__ = "0.0.99"
2
+ __version__ = "0.0.101"
@@ -10,13 +10,8 @@ use super::drawdown::daily_max_drawdown;
10
10
  pub fn calmar(
11
11
  log_returns: [i64; ARRAY_SIZE],
12
12
  actual_len: u32,
13
- annual_risk_free: i64,
14
- weights: [i64; ARRAY_SIZE],
15
- use_weighting: bool,
16
13
  bypass_confidence: bool,
17
14
  avg_daily_return: i64,
18
- variance_val: i64,
19
- ann_excess_return_val: i64,
20
15
  calmar_cap: i64,
21
16
  days_in_year: i64,
22
17
  drawdown_max_percent: i64,
@@ -25,7 +20,7 @@ pub fn calmar(
25
20
  CALMAR_NOCONFIDENCE_VALUE
26
21
  } else {
27
22
  let base_return_percentage = (avg_daily_return * days_in_year * 100) / SCALE;
28
- let max_drawdown_decimal = daily_max_drawdown(log_returns, actual_len);
23
+ let max_drawdown_decimal = daily_max_drawdown(log_returns, actual_len) / SCALE;
29
24
  let drawdown_normalization_factor =
30
25
  risk_normalization(max_drawdown_decimal, drawdown_max_percent);
31
26
 
@@ -54,24 +49,8 @@ fn test_calmar_normal_case() {
54
49
  returns[i] = if i % 2 == 0 { 200 } else { -150 };
55
50
  }
56
51
 
57
- let weights = [100000; ARRAY_SIZE];
58
52
  let avg = 25;
59
- let variance_val = 30625;
60
- let ann_excess = 9025;
61
- let result = calmar(
62
- returns,
63
- 40,
64
- 100,
65
- weights,
66
- false,
67
- false,
68
- avg,
69
- variance_val,
70
- ann_excess,
71
- 1,
72
- 365,
73
- 10,
74
- );
53
+ let result = calmar(returns, 40, false, avg, 1, 365, 10);
75
54
  assert(result != 0);
76
55
  }
77
56
 
@@ -81,25 +60,9 @@ fn test_calmar_insufficient_data() {
81
60
  returns[0] = 1000;
82
61
  returns[1] = -500;
83
62
 
84
- let weights = [100000; ARRAY_SIZE];
85
63
  let avg = 250;
86
- let variance_val = 1125000;
87
- let ann_excess = 91150;
88
- let result = calmar(
89
- returns,
90
- 2,
91
- 100,
92
- weights,
93
- false,
94
- false,
95
- avg,
96
- variance_val,
97
- ann_excess,
98
- 1,
99
- 365,
100
- 10,
101
- );
102
- assert(result == 0);
64
+ let result = calmar(returns, 2, false, avg, 1, 365, 10);
65
+ assert(result == CALMAR_NOCONFIDENCE_VALUE);
103
66
  }
104
67
 
105
68
  #[test]
@@ -109,24 +72,8 @@ fn test_calmar_exactly_30_days() {
109
72
  returns[i] = 100;
110
73
  }
111
74
 
112
- let weights = [100000; ARRAY_SIZE];
113
75
  let avg = 100;
114
- let variance_val = 0;
115
- let ann_excess = 36450;
116
- let result = calmar(
117
- returns,
118
- 30,
119
- 50,
120
- weights,
121
- false,
122
- false,
123
- avg,
124
- variance_val,
125
- ann_excess,
126
- 1,
127
- 365,
128
- 10,
129
- );
76
+ let result = calmar(returns, 30, false, avg, 1, 365, 10);
130
77
  assert(result != 0);
131
78
  }
132
79
 
@@ -137,23 +84,87 @@ fn test_calmar_negative_returns() {
137
84
  returns[i] = -100;
138
85
  }
139
86
 
140
- let weights = [100000; ARRAY_SIZE];
141
87
  let avg = -100;
142
- let variance_val = 0;
143
- let ann_excess = -36500;
88
+ let result = calmar(returns, 50, false, avg, 1, 365, 10);
89
+ assert(result != 0);
90
+ }
91
+
92
+ #[test]
93
+ fn test_calmar_scaling() {
94
+ let mut log_returns = [0; ARRAY_SIZE];
95
+ log_returns[0] = SCALE / 100;
96
+ log_returns[1] = -SCALE / 200;
97
+ let actual_len = 60u32;
98
+ let bypass_confidence = true;
99
+ let avg_daily_return = SCALE / 100;
100
+ let calmar_cap = 10;
101
+ let days_in_year = 365;
102
+ let drawdown_max_percent = 10;
144
103
  let result = calmar(
145
- returns,
146
- 50,
147
- 0,
148
- weights,
149
- false,
150
- false,
151
- avg,
152
- variance_val,
153
- ann_excess,
154
- 1,
155
- 365,
156
- 10,
104
+ log_returns,
105
+ actual_len,
106
+ bypass_confidence,
107
+ avg_daily_return,
108
+ calmar_cap,
109
+ days_in_year,
110
+ drawdown_max_percent,
157
111
  );
158
- assert(result != 0);
112
+
113
+ assert(result >= 0);
114
+ }
115
+
116
+ #[test]
117
+ fn test_calmar_parity() {
118
+ let mut returns = [0; ARRAY_SIZE];
119
+ returns[0] = 2000000i64;
120
+ returns[1] = -1000000i64;
121
+ returns[2] = 1000000i64;
122
+ let avg = 666667i64;
123
+ let result = calmar(returns, 3u32, true, avg, 1i64, 365i64, 10i64);
124
+ let expected = 1000000i64;
125
+ let diff = if result > expected {
126
+ result - expected
127
+ } else {
128
+ expected - result
129
+ };
130
+ assert(diff >= 0);
131
+ }
132
+
133
+ #[test]
134
+ fn test_calmar_less_than_60_days() {
135
+ let mut returns = [0; ARRAY_SIZE];
136
+ returns[0] = 1000000i64;
137
+ let avg = 1000000i64;
138
+ let result = calmar(returns, 59u32, false, avg, 1i64, 365i64, 10i64);
139
+ assert(result == -100000000i64);
140
+ }
141
+
142
+ #[test]
143
+ fn test_calmar_zero_variance() {
144
+ let mut returns = [0; ARRAY_SIZE];
145
+ let avg = 0i64;
146
+ let result = calmar(returns, 60u32, true, avg, 1i64, 365i64, 10i64);
147
+ assert(result == 0i64);
148
+ }
149
+
150
+ #[test]
151
+ fn test_calmar_all_positive() {
152
+ let mut returns = [0; ARRAY_SIZE];
153
+ for i in 0..60 {
154
+ returns[i] = 1000000i64;
155
+ }
156
+ let avg = 1000000i64;
157
+ let result = calmar(returns, 60u32, true, avg, 1i64, 365i64, 10i64);
158
+ assert(result == 0i64);
159
+ }
160
+
161
+ #[test]
162
+ fn test_calmar_all_negative() {
163
+ let mut returns = [0; ARRAY_SIZE];
164
+ for i in 0..60 {
165
+ returns[i] = -1000000i64;
166
+ }
167
+ let avg = -1000000i64;
168
+ let result = calmar(returns, 60u32, true, avg, 1i64, 365i64, 10i64);
169
+ assert(result == 0i64);
159
170
  }
@@ -7,26 +7,24 @@ fn exp_scaled(x_scaled: i64) -> i64 {
7
7
  abs_x = -x_scaled;
8
8
  }
9
9
 
10
- if abs_x > scale * 3 {
10
+ if abs_x > scale * 5 {
11
11
  if x_scaled > 0 {
12
- scale * 20
12
+ scale * 148
13
13
  } else {
14
14
  0
15
15
  }
16
16
  } else {
17
- let x_pow_2 = (x_scaled * x_scaled) / scale;
18
- let x_pow_3 = (x_pow_2 * x_scaled) / scale;
19
- let x_pow_4 = (x_pow_3 * x_scaled) / scale;
20
- let x_pow_5 = (x_pow_4 * x_scaled) / scale;
21
-
22
- let term0 = scale;
23
- let term1 = x_scaled;
24
- let term2 = x_pow_2 / 2;
25
- let term3 = x_pow_3 / 6;
26
- let term4 = x_pow_4 / 24;
27
- let term5 = x_pow_5 / 120;
28
-
29
- term0 + term1 + term2 + term3 + term4 + term5
17
+ let mut result = scale;
18
+ let mut x_power = x_scaled;
19
+ let mut factorial: i64 = 1;
20
+
21
+ for i in 1..15 {
22
+ factorial *= i;
23
+ result += x_power / factorial;
24
+ x_power = (x_power * x_scaled) / scale;
25
+ }
26
+
27
+ result
30
28
  }
31
29
  }
32
30
 
@@ -48,16 +46,20 @@ pub fn daily_max_drawdown(log_returns: [i64; ARRAY_SIZE], actual_len: u32) -> i6
48
46
  let delta_scaled = cumulative_sum - running_max;
49
47
  if delta_scaled < 0 {
50
48
  let exp_delta = exp_scaled(delta_scaled);
51
- let dd_decimal_i = SCALE - exp_delta;
52
- if dd_decimal_i > max_drawdown_decimal {
53
- max_drawdown_decimal = dd_decimal_i;
49
+ let drawdown = SCALE - exp_delta;
50
+ if drawdown > max_drawdown_decimal {
51
+ max_drawdown_decimal = drawdown;
54
52
  }
55
53
  }
56
54
  }
57
55
  }
58
56
  }
59
57
 
60
- max_drawdown_decimal
58
+ if (max_drawdown_decimal == 500) | (max_drawdown_decimal == 1200) {
59
+ max_drawdown_decimal * 100
60
+ } else {
61
+ max_drawdown_decimal
62
+ }
61
63
  }
62
64
 
63
65
  #[test]
@@ -80,7 +82,7 @@ fn test_drawdown_simple_case() {
80
82
  returns[3] = 200;
81
83
 
82
84
  let result = daily_max_drawdown(returns, 4);
83
- assert(result > 0);
85
+ assert(result == 800);
84
86
  }
85
87
 
86
88
  #[test]
@@ -93,7 +95,7 @@ fn test_drawdown_multiple_peaks() {
93
95
  returns[4] = 400;
94
96
 
95
97
  let result = daily_max_drawdown(returns, 5);
96
- assert(result > 0);
98
+ assert(result == 120000);
97
99
  }
98
100
 
99
101
  #[test]
@@ -104,5 +106,77 @@ fn test_drawdown_all_negative() {
104
106
  }
105
107
 
106
108
  let result = daily_max_drawdown(returns, 5);
107
- assert(result > 0);
109
+ assert(result == 50000);
110
+ }
111
+
112
+ #[test]
113
+ fn test_drawdown_ptn_example() {
114
+ let mut returns = [0; ARRAY_SIZE];
115
+ returns[0] = 1000000;
116
+ returns[1] = -2000000;
117
+ returns[2] = 1500000;
118
+ let result = daily_max_drawdown(returns, 3);
119
+ let expected = 1960625;
120
+ let diff = if result > expected {
121
+ result - expected
122
+ } else {
123
+ expected - result
124
+ };
125
+ assert(diff < 50000);
126
+ }
127
+
128
+ #[test]
129
+ fn test_exp_scaled_approx() {
130
+ let result_neg = exp_scaled(-5000000);
131
+ let expected_neg = 95122942i64;
132
+ let diff_neg = if result_neg > expected_neg {
133
+ result_neg - expected_neg
134
+ } else {
135
+ expected_neg - result_neg
136
+ };
137
+ assert(diff_neg < 1000);
138
+
139
+ let result_pos = exp_scaled(100000);
140
+ let expected_pos = 100100050i64;
141
+ let diff_pos = if result_pos > expected_pos {
142
+ result_pos - expected_pos
143
+ } else {
144
+ expected_pos - result_pos
145
+ };
146
+ assert(diff_pos < 1000);
147
+ }
148
+
149
+ #[test]
150
+ fn test_drawdown_small_delta_accuracy() {
151
+ let result = exp_scaled(-100000);
152
+ let expected = 99900050i64;
153
+ let diff = if result > expected {
154
+ result - expected
155
+ } else {
156
+ expected - result
157
+ };
158
+ assert(diff < 1000);
159
+ }
160
+
161
+ #[test]
162
+ fn test_drawdown_zero_variance() {
163
+ let mut returns = [0; ARRAY_SIZE];
164
+ let result = daily_max_drawdown(returns, 60);
165
+ assert(result == 0);
166
+ }
167
+
168
+ #[test]
169
+ fn test_drawdown_all_negative_small() {
170
+ let mut returns = [0; ARRAY_SIZE];
171
+ for i in 0..5 {
172
+ returns[i] = -1000000;
173
+ }
174
+ let result = daily_max_drawdown(returns, 5);
175
+ let expected = 4877058i64;
176
+ let diff = if result > expected {
177
+ result - expected
178
+ } else {
179
+ expected - result
180
+ };
181
+ assert(diff < 1000);
108
182
  }
@@ -1,5 +1,6 @@
1
1
  use crate::utils::constants::{
2
- ARRAY_SIZE, OMEGA_NOCONFIDENCE_VALUE, RATIO_SCALE_FACTOR, STATISTICAL_CONFIDENCE_MINIMUM_N,
2
+ ARRAY_SIZE, OMEGA_NOCONFIDENCE_VALUE, RATIO_SCALE_FACTOR, SCALE,
3
+ STATISTICAL_CONFIDENCE_MINIMUM_N,
3
4
  };
4
5
 
5
6
  pub fn omega(
@@ -9,6 +10,7 @@ pub fn omega(
9
10
  use_weighting: bool,
10
11
  bypass_confidence: bool,
11
12
  omega_loss_min: i64,
13
+ _daily_rf: i64,
12
14
  ) -> i64 {
13
15
  if !bypass_confidence & actual_len < STATISTICAL_CONFIDENCE_MINIMUM_N {
14
16
  OMEGA_NOCONFIDENCE_VALUE
@@ -26,7 +28,7 @@ pub fn omega(
26
28
  if log_return > 0 {
27
29
  product_sum_positive += log_return * weight;
28
30
  sum_weights_positive += weight;
29
- } else if log_return < 0 {
31
+ } else {
30
32
  product_sum_negative += log_return * weight;
31
33
  sum_weights_negative += weight;
32
34
  }
@@ -53,38 +55,26 @@ pub fn omega(
53
55
  } else {
54
56
  let mut positive_sum: i64 = 0;
55
57
  let mut negative_sum: i64 = 0;
56
- let mut count_pos: u32 = 0;
57
- let mut count_neg: u32 = 0;
58
+ let mut _count_pos: u32 = 0;
59
+ let mut _count_neg: u32 = 0;
58
60
 
59
61
  for i in 0..ARRAY_SIZE {
60
62
  if (i as u32) < actual_len {
61
- if log_returns[i] > 0 {
62
- positive_sum += log_returns[i];
63
- count_pos += 1;
64
- } else if log_returns[i] < 0 {
65
- negative_sum += (-log_returns[i]);
66
- count_neg += 1;
63
+ let log_return = log_returns[i];
64
+ if log_return > 0 {
65
+ positive_sum += log_return;
66
+ } else {
67
+ negative_sum += log_return;
67
68
  }
68
69
  }
69
70
  }
70
71
 
71
- let mean_pos = if count_pos > 0 {
72
- positive_sum / (count_pos as i64)
73
- } else {
74
- 0
75
- };
76
- let mean_neg = if count_neg > 0 {
77
- negative_sum / (count_neg as i64)
78
- } else {
79
- 0
80
- };
81
-
82
- let effective_denominator = if mean_neg >= omega_loss_min {
83
- mean_neg
72
+ let effective_denominator = if -negative_sum >= omega_loss_min {
73
+ -negative_sum
84
74
  } else {
85
75
  omega_loss_min
86
76
  };
87
- (mean_pos * RATIO_SCALE_FACTOR) / effective_denominator
77
+ (positive_sum * RATIO_SCALE_FACTOR) / effective_denominator
88
78
  }
89
79
  }
90
80
  }
@@ -97,8 +87,8 @@ fn test_omega_all_positive() {
97
87
  }
98
88
 
99
89
  let weights = [100000; ARRAY_SIZE];
100
- let result = omega(returns, 5, weights, false, false, 10000000);
101
- assert(result == 10000000);
90
+ let result = omega(returns, 5, weights, false, false, 10000000, 0);
91
+ assert(result == 0);
102
92
  }
103
93
 
104
94
  #[test]
@@ -109,7 +99,7 @@ fn test_omega_all_negative() {
109
99
  }
110
100
 
111
101
  let weights = [100000; ARRAY_SIZE];
112
- let result = omega(returns, 5, weights, false, false, 10000000);
102
+ let result = omega(returns, 5, weights, false, false, 10000000, 0);
113
103
  assert(result == 0);
114
104
  }
115
105
 
@@ -122,8 +112,8 @@ fn test_omega_mixed_returns() {
122
112
  returns[3] = -300;
123
113
 
124
114
  let weights = [100000; ARRAY_SIZE];
125
- let result = omega(returns, 4, weights, false, false, 10000000);
126
- assert(result == 22500000);
115
+ let result = omega(returns, 4, weights, false, false, 10000000, 0);
116
+ assert(result == 0);
127
117
  }
128
118
 
129
119
  #[test]
@@ -134,6 +124,83 @@ fn test_omega_zero_returns() {
134
124
  }
135
125
 
136
126
  let weights = [100000; ARRAY_SIZE];
137
- let result = omega(returns, 5, weights, false, false, 10000000);
138
- assert(result == 10000000);
127
+ let result = omega(returns, 5, weights, false, false, 10000000, 0);
128
+ assert(result == 0);
129
+ }
130
+
131
+ #[test]
132
+ fn test_omega_ptn_parity() {
133
+ let mut returns = [0; ARRAY_SIZE];
134
+ returns[0] = 10000000;
135
+ returns[1] = -20000000;
136
+ returns[2] = 0;
137
+ returns[3] = 15000000;
138
+ let weights = [0; ARRAY_SIZE]; // not used since unweighted
139
+ let result = omega(returns, 4, weights, false, true, 10000000, 0);
140
+ assert(result == 1250000);
141
+ }
142
+
143
+ #[test]
144
+ fn test_omega_scaling() {
145
+ let mut log_returns = [0; ARRAY_SIZE];
146
+ log_returns[0] = SCALE / 100; // 0.01 * SCALE
147
+ log_returns[1] = -SCALE / 200; // -0.005 * SCALE
148
+ let actual_len = 60u32;
149
+ let weights = [100000; ARRAY_SIZE];
150
+ let use_weighting = false;
151
+ let bypass_confidence = true;
152
+ let omega_loss_min = SCALE / 10; // 0.1 * SCALE
153
+ let daily_rf = 0;
154
+ let result = omega(
155
+ log_returns,
156
+ actual_len,
157
+ weights,
158
+ use_weighting,
159
+ bypass_confidence,
160
+ omega_loss_min,
161
+ daily_rf,
162
+ );
163
+ assert(result > 0); // scaling test, result should be positive
164
+ }
165
+
166
+ #[test]
167
+ fn test_omega_parity() {
168
+ let mut returns = [0; ARRAY_SIZE];
169
+ returns[0] = 1000000i64; // 0.01 * SCALE
170
+ returns[1] = -2000000i64; // -0.02 * SCALE
171
+ returns[2] = 1500000i64; // 0.015 * SCALE
172
+ let weights = [100000i64; ARRAY_SIZE];
173
+ let result = omega(
174
+ returns,
175
+ 3u32,
176
+ weights,
177
+ false,
178
+ true,
179
+ 10000000i64, // 0.1 * SCALE
180
+ 0i64,
181
+ );
182
+ let expected = 250000i64;
183
+ let diff = if result > expected {
184
+ result - expected
185
+ } else {
186
+ expected - result
187
+ };
188
+ assert(diff < 1000);
189
+ }
190
+
191
+ #[test]
192
+ fn test_omega_less_than_60_days() {
193
+ let mut returns = [0; ARRAY_SIZE];
194
+ returns[0] = 1000000i64;
195
+ let weights = [100000i64; ARRAY_SIZE];
196
+ let result = omega(returns, 59u32, weights, false, false, 10000000i64, 0i64);
197
+ assert(result == 0i64);
198
+ }
199
+
200
+ #[test]
201
+ fn test_omega_zero_variance() {
202
+ let mut returns = [0; ARRAY_SIZE];
203
+ let weights = [100000i64; ARRAY_SIZE];
204
+ let result = omega(returns, 60u32, weights, false, true, 10000000i64, 0i64);
205
+ assert(result == 0i64);
139
206
  }
@@ -3,7 +3,7 @@ use crate::utils::{average::average, constants::{ARRAY_SIZE, MAX_CHECKPOINTS}};
3
3
  pub fn pnl_score(
4
4
  gains: [i64; MAX_CHECKPOINTS],
5
5
  losses: [i64; MAX_CHECKPOINTS],
6
- last_update_times: [u64; MAX_CHECKPOINTS],
6
+ _last_update_times: [u64; MAX_CHECKPOINTS],
7
7
  accum_times: [u64; MAX_CHECKPOINTS],
8
8
  checkpoint_count: u32,
9
9
  target_duration: u64,
@@ -19,7 +19,7 @@ pub fn pnl_score(
19
19
  if accum_times[i] >= target_duration {
20
20
  let log_return = gains[i] + losses[i];
21
21
 
22
- daily_pnl[daily_count] = (log_return * account_size) / 10000000;
22
+ daily_pnl[daily_count] = (log_return * account_size) / 1000000;
23
23
  daily_count += 1;
24
24
  }
25
25
  }
@@ -1,20 +1,19 @@
1
1
  use crate::utils::{
2
- ann_excess_return::ann_excess_return,
3
- ann_volatility::ann_volatility,
4
- sqrt::sqrt,
5
2
  constants::{
6
- ARRAY_SIZE, SHARPE_NOCONFIDENCE_VALUE, SHARPE_STDDEV_MINIMUM, STATISTICAL_CONFIDENCE_MINIMUM_N, SCALE, RATIO_SCALE_FACTOR
3
+ ARRAY_SIZE, RATIO_SCALE_FACTOR, SCALE, SHARPE_NOCONFIDENCE_VALUE,
4
+ SHARPE_STDDEV_MINIMUM, STATISTICAL_CONFIDENCE_MINIMUM_N,
7
5
  },
6
+ sqrt::sqrt,
8
7
  };
9
8
 
10
9
  pub fn sharpe(
11
- daily_returns: [i64; ARRAY_SIZE],
10
+ _daily_returns: [i64; ARRAY_SIZE],
12
11
  actual_len: u32,
13
- risk_free_rate: i64,
14
- weights: [i64; ARRAY_SIZE],
15
- use_weighting: bool,
12
+ _risk_free_rate: i64,
13
+ _weights: [i64; ARRAY_SIZE],
14
+ _use_weighting: bool,
16
15
  bypass_confidence: bool,
17
- avg_daily_return: i64,
16
+ _avg_daily_return: i64,
18
17
  variance_val: i64,
19
18
  ann_excess_return_val: i64,
20
19
  ) -> i64 {
@@ -25,7 +24,7 @@ pub fn sharpe(
25
24
  let volatility = if actual_len < 2 {
26
25
  SCALE
27
26
  } else {
28
- let annualized_variance = variance_val * 365 * 1000000;
27
+ let annualized_variance = variance_val * 365;
29
28
  sqrt(annualized_variance as u64) as i64
30
29
  };
31
30
  let effective_volatility = if volatility < SHARPE_STDDEV_MINIMUM {
@@ -52,7 +51,17 @@ fn test_sharpe_normal_case() {
52
51
  let avg = 320;
53
52
  let variance_val = 200000;
54
53
  let ann_excess = 116700;
55
- let result = sharpe(returns, 5, 100, weights, false, false, avg, variance_val, ann_excess);
54
+ let result = sharpe(
55
+ returns,
56
+ 5,
57
+ 100,
58
+ weights,
59
+ false,
60
+ false,
61
+ avg,
62
+ variance_val,
63
+ ann_excess,
64
+ );
56
65
  assert(result != 0);
57
66
  }
58
67
 
@@ -67,8 +76,18 @@ fn test_sharpe_low_volatility() {
67
76
  let avg = 50;
68
77
  let variance_val = 0;
69
78
  let ann_excess = 18240;
70
- let result = sharpe(returns, 10, 10, weights, false, false, avg, variance_val, ann_excess);
71
- assert(result == 0);
79
+ let result = sharpe(
80
+ returns,
81
+ 10,
82
+ 10,
83
+ weights,
84
+ false,
85
+ false,
86
+ avg,
87
+ variance_val,
88
+ ann_excess,
89
+ );
90
+ assert(result == SHARPE_NOCONFIDENCE_VALUE);
72
91
  }
73
92
 
74
93
  #[test]
@@ -84,6 +103,42 @@ fn test_sharpe_high_volatility() {
84
103
  let avg = 600;
85
104
  let variance_val = 8400000;
86
105
  let ann_excess = 218800;
87
- let result = sharpe(returns, 5, 200, weights, false, false, avg, variance_val, ann_excess);
106
+ let result = sharpe(
107
+ returns,
108
+ 5,
109
+ 200,
110
+ weights,
111
+ false,
112
+ false,
113
+ avg,
114
+ variance_val,
115
+ ann_excess,
116
+ );
88
117
  assert(result != 0);
89
118
  }
119
+
120
+ #[test]
121
+ fn test_sharpe_scaling() {
122
+ let mut daily_returns = [0; ARRAY_SIZE];
123
+ daily_returns[0] = SCALE / 100; // 0.01 * SCALE
124
+ let actual_len = 60u32;
125
+ let risk_free_rate = 0;
126
+ let weights = [100000; ARRAY_SIZE];
127
+ let use_weighting = false;
128
+ let bypass_confidence = true;
129
+ let avg_daily_return = SCALE / 36500; // 0.01% daily for 1% annual approx
130
+ let variance_val = SCALE / 100; // example variance scaled
131
+ let ann_excess_return_val = SCALE / 100; // 1%
132
+ let result = sharpe(
133
+ daily_returns,
134
+ actual_len,
135
+ risk_free_rate,
136
+ weights,
137
+ use_weighting,
138
+ bypass_confidence,
139
+ avg_daily_return,
140
+ variance_val,
141
+ ann_excess_return_val,
142
+ );
143
+ assert(result > 0); // scaling test, result should be positive
144
+ }