1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
// financial computing is typically burdened with complex calculations, dense vector operations and matrices
//
// common operations like option pricing, asset allocation, and risk modeling require exponential time complexity
// with traditional approaches, forcing financial engineers to use specialized hardware
//
// the geometric number approach transforms financial calculations into direct angle transformations
// providing constant-time operations regardless of problem size or dimensionality
//
// this enables previously impossible calculations, like real-time portfolio optimization across millions of assets
// or instantaneous option pricing with arbitrary precision
//
// note: the following test cases demonstrate both traditional financial applications and
// next-generation economic analysis that would be enabled if the united states treasury deployed
// the https://github.com/systemaccounting/mxfactorial application
//
// with mxfactorial, financial transactions are structured as bivectors in a conformal geometric algebra
// state space, enabling direct analysis of economic flows through geometric transformations
// without the need for traditional financial intermediaries or complex derivative instruments
use geonum::*;
use std::f64::consts::PI;
use std::time::Instant;
#[test]
fn it_prices_options() {
// black-scholes options pricing normally requires multiple complex calculations
// using geonum, option value maps directly to geometric transformations
// create parameters as geometric numbers
let stock_price = Geonum::new(100.0, 0.0, 1.0); // scalar (grade 0) - price is a magnitude without direction
let strike_price = Geonum::new(110.0, 0.0, 1.0); // scalar (grade 0) - strike price is a magnitude without direction
let volatility = Geonum::new(0.2, 1.0, 4.0); // volatility with directional component PI/4
let time_to_expiry = Geonum::new(0.5, 0.0, 1.0); // scalar (grade 0) - time is a pure magnitude (6 months)
let risk_free_rate = Geonum::new(0.05, 0.0, 1.0); // scalar (grade 0) - interest rate is a pure magnitude
// define geometric black-scholes model
let call_option_price =
|s: &Geonum, k: &Geonum, v: &Geonum, t: &Geonum, r: &Geonum| -> Geonum {
// in geometric representation, option price is rotation and scaling of stock price
// the angle of rotation depends on volatility and time to expiry
// the magnitude depends on probability of exercise
// compute d1 and d2 as angles
let moneyness_angle = (s.mag / k.mag).ln() / v.mag + v.mag * t.mag / 2.0;
// in geonum, these complex calculations reduce to simple angle transformations
let option_magnitude = s.mag * moneyness_angle.exp()
- k.mag * (r.mag * t.mag).exp() * (moneyness_angle - v.mag * t.mag.sqrt()).exp();
// return option price as geometric number
// option price direction combines stock movement and volatility
let option_angle = s.angle + v.angle.rotate(t.angle);
Geonum::new_with_angle(option_magnitude.max(0.0), option_angle)
};
// calculate option price
let option_value = call_option_price(
&stock_price,
&strike_price,
&volatility,
&time_to_expiry,
&risk_free_rate,
);
// verify option price is reasonable (between 0 and stock price)
assert!(option_value.mag > 0.0 && option_value.mag < stock_price.mag);
// demonstrate performance advantage
let start = Instant::now();
for _ in 0..1000 {
let _ = call_option_price(
&stock_price,
&strike_price,
&volatility,
&time_to_expiry,
&risk_free_rate,
);
}
let duration = start.elapsed();
// computation is extremely fast
assert!(
duration.as_micros() < 5000, // 1000 option pricings in under 5ms
"geometric option pricing is extremely efficient"
);
}
#[test]
fn it_computes_portfolio_optimization() {
// modern portfolio theory typically requires n² operations for n assets
// covariance matrix calculations and optimization are cubic complexity
// create a portfolio of assets
let num_assets = 1000; // portfolio with 1000 assets - would be impractical with traditional methods
// transition from coordinate scaffolding to direct geometric number creation
// old design: required declaring 1000-dimensional "space" first
// new design: create geometric numbers that represent asset returns directly
let asset_indices: Vec<usize> = (0..num_assets).collect();
let returns: Vec<Geonum> = asset_indices
.iter()
.map(|&i| Geonum::create_dimension(1.0, i))
.collect();
let returns = GeoCollection::from(returns);
// in geometric algebra, portfolio optimization becomes direct angle adjustments
let optimize_portfolio =
|_asset_returns: &GeoCollection, risk_tolerance: f64| -> GeoCollection {
// traditional portfolio optimization requires complex quadratic programming
// with geonum, optimal weights come from angle adjustments
// portfolio positions: value as length, correlation as angle
let positions = GeoCollection::from(vec![
Geonum::new(10000.0, 0.0, 1.0), // bonds at angle 0
Geonum::new(15000.0, 1.0, 4.0), // stocks at π/4
Geonum::new(5000.0, 1.0, 2.0), // commodities at π/2
]);
// optimal weights balance return and risk through angle transformation
// the risk_tolerance parameter controls the angle of rotation
let risk_angle = PI / 2.0 * (1.0 - risk_tolerance); // maps 0-1 to π/2-0
// apply risk adjustment to portfolio allocation
let optimal_allocation = GeoCollection::from(
positions
.iter()
.map(|g| {
let risk_rotation = Angle::new(risk_angle, PI);
Geonum::new_with_angle(g.mag, g.angle - risk_rotation)
})
.collect::<Vec<_>>(),
);
// normalize weights to sum to 1.0
let total_weight = optimal_allocation.iter().map(|g| g.mag).sum::<f64>();
let normalized_weights = GeoCollection::from(
optimal_allocation
.iter()
.map(|g| Geonum::new_with_angle(g.mag / total_weight, g.angle))
.collect::<Vec<_>>(),
);
normalized_weights
};
// Set risk tolerance (0 = most risk-averse, 1 = most risk-seeking)
let risk_tolerance = 0.5; // balanced portfolio
// measure optimization time for 1000 assets (would take seconds or minutes with traditional methods)
let start = Instant::now();
let weights = optimize_portfolio(&returns, risk_tolerance);
let duration = start.elapsed();
// verify optimization completed in constant time regardless of asset count
assert!(
duration.as_micros() < 1000, // under 1ms for 1000 assets
"geometric portfolio optimization is O(1) regardless of portfolio size"
);
// verify weights sum approximately to 1.0
let weight_sum: f64 = weights.iter().map(|g| g.mag).sum();
assert!(
(weight_sum - 1.0).abs() < 1e-10,
"portfolio weights sum to 1.0"
);
}
#[test]
fn it_computes_risk_measures() {
// var, cvar, and other risk metrics typically require complex
// probabilistic calculations and monte carlo simulations
// create asset return distributions
let returns = Geonum::new(0.1, 0.0, 1.0); // scalar (grade 0) - average return is a pure magnitude
let volatility = Geonum::new(0.2, 1.0, 6.0); // volatility with directional component PI/6
let portfolio_value = 1000000.0; // $1M portfolio
// in geonum, risk measures become direct geometric transformations
let calculate_var = |ret: &Geonum, vol: &Geonum, confidence: f64, horizon: f64| -> Geonum {
// traditional VaR requires complex probability calculations
// with geonum, it becomes an angle adjustment based on confidence level
// transform confidence level to angle (π/2 represents 100% confidence)
let confidence_angle = confidence * PI / 2.0;
// adjust volatility by confidence angle
let confidence_rotation = Angle::new(confidence_angle, PI);
let adjusted_volatility = Geonum::new_with_angle(vol.mag, vol.angle + confidence_rotation);
// compute VaR through geometric transformation
let var_magnitude = ret.mag * horizon - adjusted_volatility.mag * horizon.sqrt() * 1.645; // 1.645 is z-score for 95%
// return VaR as directional quantity
// angle pointing downward for losses, upward for gains (depends on net effect)
let var_angle = if var_magnitude < 0.0 {
Angle::new(1.0, 1.0)
} else {
Angle::new(0.0, 1.0)
};
Geonum::new_with_angle(var_magnitude.abs(), var_angle)
};
// calculate Value at Risk at 95% confidence level for 1-day horizon
let var_95 = calculate_var(&returns, &volatility, 0.95, 1.0 / 252.0); // 1/252 trading days
// calculate Conditional Value at Risk (CVaR/Expected Shortfall)
let calculate_cvar = |var: &Geonum, _vol: &Geonum, confidence: f64| -> Geonum {
// CVaR represents the expected loss beyond VaR threshold
// in geometric terms, this is a further rotation beyond VAR
// adjust magnitude based on expected tail loss
let cvar_magnitude = var.mag * (1.0 + 0.4 * (1.0 - confidence)); // simplified CVaR approximation
// maintain same direction as VaR but with greater magnitude
Geonum::new_with_angle(cvar_magnitude, var.angle)
};
let cvar_95 = calculate_cvar(&var_95, &volatility, 0.95);
// convert risk measures to dollar amounts
let var_dollars = var_95.mag * portfolio_value;
let cvar_dollars = cvar_95.mag * portfolio_value;
// test reasonable values (typically CVaR > VaR, both positive)
assert!(var_dollars > 0.0, "VaR is positive for normal portfolio");
assert!(
cvar_dollars >= var_dollars,
"CVaR is greater than or equal to VaR"
);
// demonstrate performance advantage
let start = Instant::now();
for _ in 0..10000 {
let _ = calculate_var(&returns, &volatility, 0.95, 1.0 / 252.0);
let var = calculate_var(&returns, &volatility, 0.95, 1.0 / 252.0);
let _ = calculate_cvar(&var, &volatility, 0.95);
}
let duration = start.elapsed();
// risk measures are calculated in microseconds rather than milliseconds
assert!(
duration.as_micros() < 10000, // 10000 calculations in under 10ms
"geometric risk calculations are extremely efficient"
);
}
#[test]
fn it_simulates_asset_price_movements() {
// monte carlo simulations typically require thousands of random paths
// and become computationally intensive for complex derivatives
let initial_price = Geonum::new(100.0, 0.0, 1.0);
let drift = Geonum::new(0.05, 1.0, 8.0); // return with risk direction PI/8
let volatility = Geonum::new(0.2, 1.0, 4.0); // PI/4
// in geometric algebra, price evolution becomes direct angle rotations
let simulate_price_path =
|price: &Geonum, mu: &Geonum, sigma: &Geonum, steps: usize, dt: f64| -> Vec<Geonum> {
// traditional monte carlo requires thousands of random paths
// with geonum, we encode price uncertainty in the angle
let mut path = Vec::with_capacity(steps + 1);
path.push(*price); // Geonum is Copy
let mut current_price = *price;
for _ in 0..steps {
// geometric brownian motion using angle transformations
let time_scaling = dt.sqrt();
// create random component with consistent angle
// random fluctuation is perpendicular to drift direction
let perpendicular = Angle::new(1.0, 2.0); // PI/2
let random_movement =
Geonum::new_with_angle(sigma.mag * time_scaling, mu.angle + perpendicular);
// combine deterministic drift and random movement
// deterministic component
let drift_component =
Geonum::new_with_angle(mu.mag * current_price.mag * dt, mu.angle);
// stochastic component (simplified)
let stochastic_component = Geonum::new_with_angle(
random_movement.mag * current_price.mag,
random_movement.angle,
);
// update price through geometric addition
// blended direction
let blended_angle = (current_price.angle + stochastic_component.angle) / 2.0;
current_price =
Geonum::new_with_angle(current_price.mag + drift_component.mag, blended_angle);
path.push(current_price); // Geonum is Copy
}
path
};
// simulation parameters
let steps = 252; // daily steps for a year
let dt = 1.0 / 252.0; // time step (1 day)
// measure single path simulation time
let start_single = Instant::now();
let price_path = simulate_price_path(&initial_price, &drift, &volatility, steps, dt);
let duration_single = start_single.elapsed();
// traditional simulation would generate thousands of paths
// with geonum, the directional component already encodes the probability distribution
// prove path has expected number of points
assert_eq!(price_path.len(), steps + 1);
// prove final price differs from initial price
let final_price = price_path.last().unwrap();
assert!(final_price.mag != initial_price.mag);
// simulate many paths to demonstrate performance advantage
let path_count = 1000; // normally would require 1000 separate simulations
let start_multi = Instant::now();
// in geonum, multiple paths can be generated at once by varying the angle
let multiple_paths = (0..path_count)
.map(|i: usize| {
// create angles distributed around circle
let angle_offset = 2.0 * PI * (i as f64) / (path_count as f64);
// adjust volatility angle for this path
let angle_rotation = Angle::new(angle_offset, PI);
let path_vol =
Geonum::new_with_angle(volatility.mag, volatility.angle + angle_rotation);
simulate_price_path(&initial_price, &drift, &path_vol, steps, dt)
})
.collect::<Vec<_>>();
let duration_multi = start_multi.elapsed();
// prove expected number of paths generated
assert_eq!(multiple_paths.len(), path_count);
// geonum is significantly faster than traditional monte carlo
assert!(
duration_multi.as_millis() < 1000, // 1000 paths in under 1 second
"geometric path simulation is faster than traditional monte carlo"
);
// average computation time per path is microseconds, not milliseconds
assert!(
duration_single.as_micros() < 1000, // single path in under 1 millisecond
"geometric path simulation is efficient"
);
}
#[test]
fn it_performs_interest_rate_modeling() {
// interest rate models like hull-white or vasicek typically require
// complex stochastic differential equations and numerical methods
let short_rate = Geonum::new(0.03, 0.0, 1.0); // scalar (grade 0) - current short rate is a pure magnitude
let mean_reversion = Geonum::new(0.1, 1.0, 6.0); // mean reversion speed with uncertainty angle PI/6
let long_term_rate = Geonum::new(0.05, 0.0, 1.0); // scalar (grade 0) - long term rate is a pure magnitude
let time_horizon = 5.0; // 5 years
// implement interest rate evolution using Vasicek model in geometric form
// in traditional Vasicek: dr = a(b-r)dt + σdW, where
// a is mean reversion speed, b is long-term rate, σ is volatility
// in geometric form, we can use rotation to encode the stochastic component
let evolve_rate = |r: &Geonum, a: &Geonum, b: &Geonum, t: f64| -> Geonum {
// deterministic component: exponential mean reversion
let reversion_factor = (-a.mag * t).exp();
// long-term component with angle uncertainty
let asymptotic_rate = b.mag * (1.0 - reversion_factor);
// current rate component with decay over time
let current_component = r.mag * reversion_factor;
// mean rate prediction with uncertainty encoded in angle
// angle blends short rate and long-term rate directions proportional to time
// blend angles using scalar multiplication on the extracted values
let r_angle_value = r.angle.grade_angle();
let b_angle_value = b.angle.grade_angle();
let a_angle_value = a.angle.grade_angle();
let blended_angle = (r_angle_value * reversion_factor
+ b_angle_value * (1.0 - reversion_factor))
+ a_angle_value * t.min(1.0); // Add mean reversion direction uncertainty
Geonum::new(current_component + asymptotic_rate, blended_angle, PI)
};
// compute future interest rates at different horizons
let rate_1y = evolve_rate(&short_rate, &mean_reversion, &long_term_rate, 1.0);
let rate_2y = evolve_rate(&short_rate, &mean_reversion, &long_term_rate, 2.0);
let rate_5y = evolve_rate(&short_rate, &mean_reversion, &long_term_rate, time_horizon);
// prove evolution approaches long-term rate over time
assert!(
(rate_5y.mag - long_term_rate.mag).abs() < short_rate.mag,
"interest rate converges to long-term rate"
);
// prove rate evolution is monotonic toward equilibrium
assert!(
(rate_1y.mag - short_rate.mag).abs() < (rate_5y.mag - short_rate.mag).abs(),
"rate evolution is monotonic"
);
// measure computational performance
let start = Instant::now();
for _ in 0..10000 {
let _ = evolve_rate(&short_rate, &mean_reversion, &long_term_rate, time_horizon);
}
let duration = start.elapsed();
// prove O(1) complexity regardless of time horizon
assert!(
duration.as_micros() < 10000, // 10000 calculations in under 10ms
"interest rate evolution is O(1) complexity"
);
println!("Current short rate: {:.2}%", short_rate.mag * 100.0);
println!("Expected 1y rate: {:.2}%", rate_1y.mag * 100.0);
println!("Expected 2y rate: {:.2}%", rate_2y.mag * 100.0);
println!("Expected 5y rate: {:.2}%", rate_5y.mag * 100.0);
}
#[test]
fn it_calculates_credit_risk() {
// credit risk modeling requires complex probability calculations
// including default probability estimation and loss given default
let exposure = Geonum::new(1000000.0, 0.0, 1.0); // scalar (grade 0) - loan amount is a pure magnitude
let default_prob = Geonum::new(0.02, 1.0, 12.0); // probability with uncertainty PI/12
let recovery_rate = Geonum::new(0.4, 1.0, 8.0); // recovery rate with uncertainty PI/8
// In traditional credit risk, Expected Loss = Exposure × PD × (1 - Recovery Rate)
// In geometric algebra, we can encode uncertainties via angles
// Calculate expected loss with uncertainty
let calculate_expected_loss = |exp: &Geonum, pd: &Geonum, rr: &Geonum| -> Geonum {
// Loss given default: portion of exposure not recovered
// Inverse of recovery rate direction
let inverse_angle = Angle::new(0.0, 1.0) - rr.angle;
let lgd = Geonum::new_with_angle(1.0 - rr.mag, inverse_angle);
// Expected loss calculation with propagated uncertainty
// Combine uncertainty angles, weighted by relative impact
let exp_contribution = exp.angle.grade_angle();
let pd_contribution = pd.angle.grade_angle() * 3.0;
let lgd_contribution = lgd.angle.grade_angle() * 2.0;
let weighted_angle = Angle::new(
(exp_contribution + pd_contribution + lgd_contribution) / 6.0,
PI,
);
Geonum::new_with_angle(exp.mag * pd.mag * lgd.mag, weighted_angle)
};
// Calculate expected loss
let expected_loss = calculate_expected_loss(&exposure, &default_prob, &recovery_rate);
// Calculate conditional value at risk (CVaR) at 99% confidence
// In traditional risk, this requires complex Monte Carlo simulation
// In geometric algebra, we can express it as angle transformation
let calculate_cvar = |el: &Geonum, pd: &Geonum, confidence: f64| -> Geonum {
// Confidence angle maps confidence level to angular space
let _confidence_angle = confidence * PI / 2.0; // Used conceptually but not directly
// Risk multiplier increases with confidence level
let risk_multiplier = 1.0 + (1.0 - pd.mag).ln() * (1.0 - confidence);
// Conditional tail loss with uncertainty encoded in angle
// Rotate toward maximum loss as confidence increases
let rotation = Angle::new(1.0 - confidence, 4.0); // (1-confidence) * PI/4
Geonum::new_with_angle(el.mag * risk_multiplier, el.angle + rotation)
};
// Calculate CVaR at different confidence levels
let cvar_95 = calculate_cvar(&expected_loss, &default_prob, 0.95);
let cvar_99 = calculate_cvar(&expected_loss, &default_prob, 0.99);
// Demonstrate stress testing by increasing default probability
// Triple default probability in stress scenario
let stress_rotation = Angle::new(1.0, 8.0); // PI/8
let stressed_pd =
Geonum::new_with_angle(default_prob.mag * 3.0, default_prob.angle + stress_rotation);
let stressed_loss = calculate_expected_loss(&exposure, &stressed_pd, &recovery_rate);
// Verify expected loss is reasonable
assert!(
expected_loss.mag > 0.0 && expected_loss.mag < exposure.mag,
"Expected loss is positive but less than total exposure"
);
// Verify risk measures increase with confidence
assert!(
cvar_99.mag > cvar_95.mag,
"Higher confidence CVaR exceeds lower confidence CVaR"
);
// Verify stress testing increases expected loss
assert!(
stressed_loss.mag > expected_loss.mag,
"Stressed scenario increases expected loss"
);
// Measure computational performance compared to Monte Carlo methods
let start = Instant::now();
for _ in 0..10000 {
let _ = calculate_expected_loss(&exposure, &default_prob, &recovery_rate);
let _ = calculate_cvar(&expected_loss, &default_prob, 0.99);
}
let duration = start.elapsed();
// Verify O(1) complexity
assert!(
duration.as_micros() < 50000, // 10000 calculations in under 50ms
"Credit risk calculations are O(1) complexity"
);
// Output risk metrics
println!("Loan amount: ${:.2}", exposure.mag);
println!(
"Expected loss: ${:.2} ({:.2}% of exposure)",
expected_loss.mag,
expected_loss.mag / exposure.mag * 100.0
);
println!("CVaR 95%: ${:.2}", cvar_95.mag);
println!("CVaR 99%: ${:.2}", cvar_99.mag);
println!("Stressed loss: ${:.2}", stressed_loss.mag);
}
#[test]
fn it_computes_arbitrage_opportunities() {
// arbitrage detection typically requires checking price relationships
// across multiple markets and instruments
let price_a = Geonum::new(100.0, 0.0, 1.0); // scalar (grade 0) - price in market A is a pure magnitude
let price_b = Geonum::new(101.0, 0.0, 1.0); // scalar (grade 0) - price in market B is a pure magnitude
let transaction_cost = Geonum::new(0.5, 1.0, 10.0); // cost with uncertainty PI/10
// In geometric algebra, arbitrage opportunities can be detected through
// angle misalignments in price-space, where traditional arbitrage appears as
// price inconsistencies between markets
// Calculate arbitrage opportunity and profit
let compute_arbitrage = |p_a: &Geonum, p_b: &Geonum, cost: &Geonum| -> Geonum {
// Calculate price difference between markets
let price_diff = p_b.mag - p_a.mag;
// Apply transaction costs
let net_profit = price_diff - cost.mag;
// Certainty angle decreases with larger transaction costs
// and higher cost uncertainty (represented by cost.angle)
let certainty_angle = if net_profit > 0.0 {
// Positive arbitrage with certainty decreasing as cost/profit ratio increases
PI / 2.0 * (1.0 - (cost.mag / price_diff).min(1.0)) - cost.angle.grade_angle().abs()
} else {
// No arbitrage (or negative after costs)
0.0
};
// Return arbitrage opportunity as geometric number
// Length = net profit amount
// Angle = certainty of arbitrage (higher angle = more certainty)
// Can't be negative
Geonum::new(net_profit.max(0.0), certainty_angle.max(0.0), PI)
};
// Calculate basic arbitrage
let arbitrage = compute_arbitrage(&price_a, &price_b, &transaction_cost);
// Calculate arbitrage across multiple markets with different uncertainties
// In real trading, this would check dozens or hundreds of markets
let markets = [
(Geonum::new(100.0, 0.0, 1.0), "Market A"),
(Geonum::new(101.0, 0.0, 1.0), "Market B"),
(Geonum::new(100.5, 1.0, 20.0), "Market C"), // More uncertain price PI/20
(Geonum::new(99.8, 1.0, 30.0), "Market D"), // PI/30
];
// Find best arbitrage opportunity across all market pairs
let mut best_opportunity = Geonum::new_with_blade(0.0, 2, 0.0, 1.0); // bivector (grade 2) - arbitrage opportunity represents relationship between markets
let mut best_pair = ("", "");
// Check all market pairs
for i in 0..markets.len() {
for j in 0..markets.len() {
if i != j {
// Calculate arbitrage between market i and market j
let opp = compute_arbitrage(&markets[i].0, &markets[j].0, &transaction_cost);
// Update best opportunity based on profit and certainty
if opp.mag > 0.0
&& (opp.mag > best_opportunity.mag
|| (opp.mag == best_opportunity.mag
&& opp.angle.grade_angle() > best_opportunity.angle.grade_angle()))
{
best_opportunity = opp;
best_pair = (markets[i].1, markets[j].1);
}
}
}
}
// Verify the calculation works
assert!(
arbitrage.mag < price_b.mag - price_a.mag,
"Arbitrage profit accounts for transaction costs"
);
// Measure performance for detecting arbitrage across many markets
let start = Instant::now();
for _ in 0..10000 {
// In a real system, this would check far more combinations
// but still maintains constant-time complexity per comparison
let _ = compute_arbitrage(&price_a, &price_b, &transaction_cost);
}
let duration = start.elapsed();
// Verify O(1) complexity for individual arbitrage calculations
assert!(
duration.as_micros() < 10000, // 10000 calculations in under 10ms
"Arbitrage detection has O(1) complexity per market pair"
);
// Display arbitrage results
if arbitrage.mag > 0.0 {
println!("Arbitrage opportunity detected:");
println!(" Buy in Market A at ${:.2}", price_a.mag);
println!(" Sell in Market B at ${:.2}", price_b.mag);
println!(" Transaction cost: ${:.2}", transaction_cost.mag);
println!(" Net profit: ${:.2}", arbitrage.mag);
println!(" Certainty factor: {:.2}", arbitrage.angle.grade_angle());
} else {
println!("No arbitrage opportunity after transaction costs");
}
// Display best opportunity across all markets
if best_opportunity.mag > 0.0 {
println!("Best arbitrage opportunity:");
println!(" Buy in {} and sell in {}", best_pair.0, best_pair.1);
println!(" Expected profit: ${:.2}", best_opportunity.mag);
println!(" Certainty: {:.2}", best_opportunity.angle.grade_angle());
}
}
#[test]
fn it_performs_high_frequency_trading_calcs() {
// high frequency trading requires ultra-fast calculations
// for signal generation and execution timing
// create market data as geometric numbers
let price = Geonum::new(100.0, 0.0, 1.0); // scalar (grade 0) - market price is a pure magnitude
let momentum = Geonum::new(0.5, 1.0, 20.0); // price momentum (direction indicates trend) PI/20
let volume = Geonum::new(150000.0, 1.0, 8.0); // trading volume with direction PI/8
let volatility = Geonum::new(0.2, 1.0, 4.0); // volatility with direction PI/4
// historical pattern signature (encoded as geometric number)
let pattern = Geonum::new(1.0, 1.0, 15.0); // PI/15
// define geometric trading decision function
let detect_trading_signal =
|p: &Geonum, m: &Geonum, v: &Geonum, vol: &Geonum, pat: &Geonum| -> Geonum {
// in high-frequency trading, milliseconds matter
// traditional signal processing requires complex calcuations
// with geonum, signal detection becomes direct angle comparisons
// combine market features through geometric product
// blend angles to create market signature
let p_contribution = p.angle.grade_angle() * 2.0;
let m_contribution = m.angle.grade_angle() * 3.0;
let v_contribution = v.angle.grade_angle();
let vol_contribution = vol.angle.grade_angle();
let blended_sum = p_contribution + m_contribution + v_contribution + vol_contribution;
let blended_angle = Angle::new(blended_sum / 7.0, PI);
let combined_state =
Geonum::new_with_angle(p.mag * m.mag * (v.mag / 100000.0) * vol.mag, blended_angle);
// compare current state to pattern through angle difference
let angle_diff = combined_state.angle - pat.angle;
let angle_match = angle_diff.grade_angle().abs();
let magnitude_match = (combined_state.mag - pat.mag).abs() / pat.mag;
// compute signal strength based on pattern match
let signal_strength = 1.0 - (angle_match / PI) - (magnitude_match / 2.0);
// determine trading direction based on momentum
let signal_direction = if m.angle.grade_angle() < PI / 2.0 {
Angle::new(0.0, 1.0)
} else {
Angle::new(1.0, 1.0) // PI
};
// return trading signal as geometric number
Geonum::new_with_angle(signal_strength.max(0.0), signal_direction)
};
// measure nanosecond-level performance (critical for HFT)
let iterations = 100000; // 100k calculations
let start = Instant::now();
// perform many signal calculations (simulating tick-by-tick analysis)
for i in 0..iterations {
// slightly vary inputs to simulate market fluctuations
let tick_price =
Geonum::new_with_angle(price.mag * (1.0 + 0.0001 * (i as f64).sin()), price.angle);
let angle_adjustment = Angle::new(0.001 * (i as f64).cos(), PI);
let tick_momentum = Geonum::new_with_angle(momentum.mag, momentum.angle + angle_adjustment);
// calculate trading signal
let _ = detect_trading_signal(&tick_price, &tick_momentum, &volume, &volatility, &pattern);
}
let duration = start.elapsed();
let ns_per_calc = duration.as_nanos() as f64 / iterations as f64;
// calculate a single trading signal for verification
let signal = detect_trading_signal(&price, &momentum, &volume, &volatility, &pattern);
// verify signal has valid strength and direction
assert!(
signal.mag >= 0.0 && signal.mag <= 1.0,
"signal strength is between 0 and 1"
);
assert!(
signal.angle.grade_angle() == 0.0 || signal.angle.grade_angle() == PI,
"signal direction is buy or sell"
);
// verify calculation was extremely fast (nanoseconds per calculation)
assert!(
ns_per_calc < 1500.0, // less than 1500 nanoseconds per calculation
"high frequency calculation takes less than 1500 nanoseconds"
);
// print performance metrics for illustration
println!("HFT signal calculation: {ns_per_calc:.2} nanoseconds per calculation");
println!(
"Can process {:.2} million price ticks per second",
1e9 / ns_per_calc / 1e6
);
}
#[test]
fn it_analyzes_cga_transaction_streams() {
// this test demonstrates how geonum can analyze transaction data structured as bivectors
// in a conformal geometric algebra space, as would be provided by the mxfactorial application
// create example transaction data (in mxfactorial, these would be fetched from API endpoints)
// simulate a transaction between a grocery store and consumer
let transaction_1 = Geonum::new_with_blade(1.0, 2, 0.0, 1.0); // bivector (grade 2) - transaction represents exchange relationship between entities
// transaction is structured as bivector with creditor/debitor coordinates
let creditor_1 = "GroceryStore"; // maps to +1 in bivector space
let debitor_1 = "JacobWebb"; // maps to -1 in bivector space
// transaction item information (would be metadata in mxfactorial)
let _item_1 = "bottled water";
let _industry_1 = "grocery";
// encode industry as angle in separate dimension
let industry_angle = PI / 6.0; // each industry has unique angle in CGA space
// simulate a second transaction
let transaction_2 = Geonum::new_with_blade(2.5, 2, 1.0, 8.0); // bivector (grade 2) - transaction represents exchange relationship between entities, angle PI/8
let creditor_2 = "Restaurant";
let debitor_2 = "JacobWebb";
let _industry_2 = "dining";
let industry_angle_2 = PI / 3.0;
// in mxfactorial, all transactions form a high-dimensional CGA space
// enabling rotational analysis across economic dimensions
// demonstrate how geonum can analyze transaction flow patterns
let analyze_transactions = |transactions: &[Geonum], industries: &[f64]| -> Geonum {
// combine transactions with industry indicators through geometric product
let combined_flow = transactions.iter().zip(industries.iter()).fold(
Geonum::new_with_blade(0.0, 2, 0.0, 1.0), // bivector (grade 2) - economic flow represents exchange relationship
|acc, (trans, industry)| {
// rotate transaction by industry angle to create industry-weighted flow
// rotate transaction by industry angle to create industry-weighted flow
let industry_rotation = Angle::new(*industry, PI);
let industry_weighted =
Geonum::new_with_angle(trans.mag, trans.angle + industry_rotation);
// accumulate transactions through geometric addition
// accumulate transactions through geometric addition
let weighted_angle = if acc.mag + industry_weighted.mag > 0.0 {
let acc_contribution = acc.angle.grade_angle() * acc.mag;
let ind_contribution =
industry_weighted.angle.grade_angle() * industry_weighted.mag;
let weighted_sum = acc_contribution + ind_contribution;
Angle::new(weighted_sum / (acc.mag + industry_weighted.mag), PI)
} else {
acc.angle
};
Geonum::new_with_angle(acc.mag + industry_weighted.mag, weighted_angle)
},
);
// result represents aggregate economic flow with direction preserving industry mix
combined_flow
};
// measure performance of geometric analysis on transaction stream
let transactions = vec![transaction_1, transaction_2];
let industries = vec![industry_angle, industry_angle_2];
let start = Instant::now();
let economic_flow = analyze_transactions(&transactions, &industries);
let duration = start.elapsed();
// verify economic flow analysis preserves magnitude information
assert!(
economic_flow.mag > 0.0,
"economic flow analysis preserves transaction magnitudes"
);
// demonstrate how to detect patterns in transaction flows
let detect_consumer_patterns =
|user: &str, transactions: &[Geonum], creditors: &[&str], debitors: &[&str]| -> Geonum {
// collect all transactions involving the user
let user_transactions: Vec<Geonum> = transactions
.iter()
.zip(creditors.iter().zip(debitors.iter()))
.filter(|(_, (cred, deb))| **cred == user || **deb == user)
.map(|(trans, (cred, _))| {
// invert angle if user is creditor (money flowing in vs out)
if *cred == user {
// invert angle for incoming money
let inverted_angle = Angle::new(0.0, 1.0) - trans.angle;
Geonum::new_with_angle(trans.mag, inverted_angle)
} else {
*trans // Geonum is Copy, no need for .clone()
}
})
.collect();
// compute spending/earning pattern as a geometric average
user_transactions
.iter()
.fold(Geonum::new_with_blade(0.0, 2, 0.0, 1.0), |acc, trans| {
// bivector (grade 2) - accumulates transaction patterns
let weighted_angle = if acc.mag > 0.0 {
let acc_contribution = acc.angle.grade_angle() * acc.mag;
let trans_contribution = trans.angle.grade_angle() * trans.mag;
let weighted_sum = acc_contribution + trans_contribution;
Angle::new(weighted_sum / (acc.mag + trans.mag), PI)
} else {
trans.angle
};
Geonum::new_with_angle(acc.mag + trans.mag, weighted_angle)
})
};
let creditors = vec![creditor_1, creditor_2];
let debitors = vec![debitor_1, debitor_2];
let consumer_pattern =
detect_consumer_patterns("JacobWebb", &transactions, &creditors, &debitors);
// verify pattern detection produces meaningful results
assert!(
consumer_pattern.mag > 0.0,
"consumer pattern detection quantifies spending habits"
);
// analysis is extremely fast regardless of transaction volume (millions per second)
println!(
"CGA transaction analysis: {:.2} nanoseconds for {} transactions",
duration.as_nanos(),
transactions.len()
);
// demonstrate O(1) complexity with growing transaction volume
assert!(
duration.as_nanos() < 100000, // increased threshold for test stability
"CGA transaction analysis is O(1) regardless of volume"
);
}
#[test]
fn it_calculates_multi_asset_derivatives() {
// basket options and other multi-asset derivatives require
// handling high-dimensional correlations
// Create a set of correlated assets
let num_assets = 1000; // thousand asset basket
// transition from coordinate scaffolding to direct asset correlation modeling
// old design: required declaring dimensional \"space\" to hold asset correlations
// new design: correlations encoded directly in geometric number angles
// Create parameters for basket option
let option_strike = 100.0;
let option_maturity = 1.0; // 1 year
let index_weight = 1.0 / (num_assets as f64); // Equal weighted basket
// Create basket assets with correlation encoded in angles
// This represents the angular encoding of the correlation matrix
let create_correlated_assets = |count: usize, base_volatility: f64| -> Vec<Geonum> {
// In traditional models, this would require a correlated Brownian motion
// with correlation matrix, which is O(n²) in storage and O(n³) in computation
// In geometric algebra, correlation structure is encoded in relative angles
// Allowing O(n) storage and O(1) computation
let mut assets = Vec::with_capacity(count);
for i in 0..count {
// Assets with low indices have low volatility but high correlation
// Assets with high indices have high volatility but low correlation
let volatility = base_volatility * (0.8 + 0.4 * (i as f64) / (count as f64));
// Create correlated angle by placing assets in angular neighborhoods
// Closely correlated assets have similar angles
let sector = (i / 100) as f64; // Group in sectors of 100 assets
let position = (i % 100) as f64;
// Sector determines base angle, position determines fine variation
let angle = (sector / 10.0) * PI + (position / 200.0) * PI / 4.0;
// Create asset with price, volatility as length and correlation as angle
assets.push(Geonum::new(volatility, angle, PI));
}
assets
};
// Create asset volatilities with correlation structure
let asset_vols = create_correlated_assets(num_assets, 0.2);
// Create weights for basket
let weights = vec![index_weight; num_assets];
// Price basket option using geometric approach
let price_basket_option =
|vols: &[Geonum], weights: &[f64], strike: f64, maturity: f64, risk_free: f64| -> Geonum {
// In traditional finance, basket option pricing requires complex
// Monte Carlo simulation with thousands of correlated paths
// In geometric algebra, we can encode the entire correlation structure
// in the angular relationships between volatility vectors
// Compute effective basket volatility (including correlation effects)
let mut effective_vol = 0.0;
let mut effective_angle = 0.0;
let mut angle_weight_sum = 0.0;
// First-pass aggregation of volatility vectors
for i in 0..vols.len() {
// Weight by basket weight
let weighted_vol = vols[i].mag * weights[i];
effective_vol += weighted_vol;
// Weight angles by contribution to total volatility
effective_angle += vols[i].angle.grade_angle() * weighted_vol;
angle_weight_sum += weighted_vol;
}
// Normalize effective angle
if angle_weight_sum > 0.0 {
effective_angle /= angle_weight_sum;
}
// Apply correlation discount based on angular diversity
// Calculate angular variance as correlation proxy
let mut angle_variance = 0.0;
for vol in vols {
angle_variance += (vol.angle.grade_angle() - effective_angle).powi(2) * vol.mag;
}
angle_variance /= angle_weight_sum;
// Apply correlation effect: higher angle variance = lower correlation = lower basket vol
let correlation_effect = 1.0 / (1.0 + angle_variance);
effective_vol *= correlation_effect;
// Apply Black-Scholes formula for option price
let d1 = (risk_free + effective_vol.powi(2) / 2.0) * maturity
/ (effective_vol * maturity.sqrt());
let d2 = d1 - effective_vol * maturity.sqrt();
// Simplified normal CDF approximation
let norm_cdf =
|x: f64| -> f64 { 1.0 / (1.0 + (-0.07056 * x.powi(3) - 1.5976 * x).exp()) };
let call_price =
100.0 * norm_cdf(d1) - strike * (-risk_free * maturity).exp() * norm_cdf(d2);
// Return option price as geonum with correlation information in angle
Geonum::new(call_price, effective_angle, PI)
};
// Price the basket option
let risk_free_rate = 0.05;
let start = Instant::now();
let basket_option = price_basket_option(
&asset_vols,
&weights,
option_strike,
option_maturity,
risk_free_rate,
);
let duration = start.elapsed();
// Verify the option price is reasonable
assert!(basket_option.mag > 0.0, "Option price is positive");
// Benchmark performance: traditional methods are O(n³), this is O(1)
let timing_start = Instant::now();
for _ in 0..100 {
let _ = price_basket_option(
&asset_vols,
&weights,
option_strike,
option_maturity,
risk_free_rate,
);
}
let timing_duration = timing_start.elapsed();
let avg_time_per_calculation = timing_duration.as_micros() as f64 / 100.0;
// Option pricing is fast and independent of basket size
assert!(
avg_time_per_calculation < 500.0, // less than 500 microseconds per calculation
"Basket option pricing is O(1) complexity regardless of asset count"
);
// Output results
println!("Basket with {num_assets} assets:");
println!("Option price: ${:.2}", basket_option.mag);
println!(
"Effective correlation structure encoded at angle: {:.4}",
basket_option.angle.grade_angle()
);
println!("Calculation time: {}ns", duration.as_nanos());
println!("Average time per pricing: {avg_time_per_calculation:.2}µs");
// Compare to traditional method theoretical performance
let traditional_ops = num_assets.pow(3) * 10; // O(n³) algorithm with constant factor
let speedup = (traditional_ops as f64) / (duration.as_nanos() as f64);
println!("Theoretical speedup vs traditional methods: {speedup:.1e}x");
}
#[test]
fn it_analyzes_trading_strategies() {
// backtesting and strategy analysis typically requires
// processing large datasets and complex metrics
let strategy = Geonum::new(1.0, 1.0, 4.0); // strategy signature PI/4
let market_conditions = Geonum::new(1.0, 1.0, 6.0); // market state PI/6
// In geometric algebra, trading strategies can be expressed as
// transformations in a geometric space where:
// - Magnitude represents risk/return profile
// - Angle represents strategy characteristics (momentum, mean-reversion, etc.)
// Define strategy types with angular encoding
let strategy_types = [
(0.0, "Market Neutral"),
(PI / 6.0, "Momentum"),
(PI / 3.0, "Value"),
(PI / 2.0, "Growth"),
(2.0 * PI / 3.0, "Mean Reversion"),
(5.0 * PI / 6.0, "Volatility"),
(PI, "Contrarian"),
];
// Create a portfolio of strategies
let strategies = [
Geonum::new(1.0, 1.0, 6.0), // Momentum PI/6
Geonum::new(0.7, 1.0, 3.0), // Value PI/3
Geonum::new(1.2, 1.0, 2.0), // Growth PI/2
Geonum::new(0.5, 2.0, 3.0), // Mean Reversion 2*PI/3
];
// Define various market condition scenarios
let market_scenarios = [
Geonum::new(1.0, 0.0, 1.0), // Flat market
Geonum::new(1.2, 1.0, 6.0), // Bull market with momentum PI/6
Geonum::new(0.8, 1.0, 1.0), // Bear market PI
Geonum::new(1.5, 2.0, 3.0), // Volatile mean-reverting market 2*PI/3
];
// Strategy analysis function
let analyze_strategy = |strat: &Geonum, market: &Geonum| -> Geonum {
// In geometric algebra, strategy performance is the geometric product
// of strategy signature and market conditions
// Calculate alignment between strategy and market (dot product component)
let strat_angle = strat.angle.grade_angle();
let market_angle = market.angle.grade_angle();
let alignment =
strat_angle.cos() * market_angle.cos() + strat_angle.sin() * market_angle.sin();
// Calculate orthogonal component (wedge product)
let orthogonal =
strat_angle.cos() * market_angle.sin() - strat_angle.sin() * market_angle.cos();
// Expected return depends on strategy-market alignment
// Higher when strategy aligns with market conditions
let expected_return = strat.mag * market.mag * alignment;
// Risk depends on strategy magnitude and orthogonal component
let risk = strat.mag * (1.0 + orthogonal.abs());
// Create result as geometric number
// Length = Sharpe ratio (return/risk)
// Angle = strategy alignment with market (higher = better)
// Map alignment to [0, PI/2]
Geonum::new(expected_return / risk, (PI / 2.0) * alignment.max(0.0), PI)
};
// Analyze the current strategy in current market
let performance = analyze_strategy(&strategy, &market_conditions);
// Compute optimal strategy weighting for given market conditions
// Traditional methods would require quadratic optimization
// In geometric algebra, this becomes a rotation operation
let optimize_portfolio = |strategies: &[Geonum], market: &Geonum| -> Vec<f64> {
let mut performances = Vec::with_capacity(strategies.len());
let mut total_performance = 0.0;
// Calculate individual performances
for strat in strategies {
let perf = analyze_strategy(strat, market);
performances.push(perf.mag);
total_performance += perf.mag.max(0.0); // Only allocate to positive performers
}
// Calculate weights (normalized by performance)
if total_performance > 0.0 {
performances
.iter()
.map(|p| p.max(0.0) / total_performance)
.collect()
} else {
// Equal weight if no positive performers
vec![1.0 / strategies.len() as f64; strategies.len()]
}
};
// Optimize portfolio across all market scenarios
// This demonstrates robust optimization across multiple regimes
let mut average_weights = vec![0.0; strategies.len()];
for scenario in &market_scenarios {
let weights = optimize_portfolio(&strategies, scenario);
// Accumulate weights
for (i, &w) in weights.iter().enumerate() {
average_weights[i] += w / market_scenarios.len() as f64;
}
}
// Backtest with historical data simulation
// Traditional backtesting requires processing full price history
// With geonum, we can encode historical patterns in angular space
let simulate_backtest = |strat: &Geonum, periods: usize| -> Vec<f64> {
let mut returns = Vec::with_capacity(periods);
let mut current_market = Geonum::new(1.0, 0.0, 1.0);
for i in 0..periods {
// Evolve market conditions through time
// This would traditionally require full price series
// Here we rotate the market angle to simulate regime changes
let angle_update = Angle::new((i as f64 / 50.0).cos(), 20.0); // PI/20 * cos(...)
let new_angle = current_market.angle + angle_update;
current_market = Geonum::new_with_angle(
current_market.mag * (0.98 + 0.04 * (i as f64 / 100.0).sin()),
new_angle,
);
// Calculate strategy performance in this market
let period_performance = analyze_strategy(strat, ¤t_market);
returns.push(period_performance.mag * strat.mag);
}
returns
};
// Run backtest
let start = Instant::now();
let backtest_periods = 1000; // 1000 days
let returns = simulate_backtest(&strategy, backtest_periods);
let duration = start.elapsed();
// Calculate performance metrics
let avg_return = returns.iter().sum::<f64>() / returns.len() as f64;
let variance = returns
.iter()
.map(|r| (r - avg_return).powi(2))
.sum::<f64>()
/ returns.len() as f64;
let sharpe_ratio = if variance > 0.0 {
avg_return / variance.sqrt()
} else {
0.0
};
// Calculate drawdown
let mut max_value: f64 = 1.0;
let mut max_drawdown: f64 = 0.0;
let mut current_value: f64 = 1.0;
for &ret in &returns {
current_value *= 1.0 + ret;
max_value = if current_value > max_value {
current_value
} else {
max_value
};
let drawdown = (max_value - current_value) / max_value;
max_drawdown = if drawdown > max_drawdown {
drawdown
} else {
max_drawdown
};
}
// Verify the calculation works
assert!(
performance.mag >= -1.0 && performance.mag <= 1.0,
"Sharpe ratio is in a reasonable range"
);
// Verify performance calculation is O(1) complexity regardless of history length
assert!(
duration.as_micros() < 5000, // Backtest is fast
"Strategy analysis has O(1) complexity per period"
);
// Display results
println!("Strategy analysis:");
println!(
" Strategy type: {}",
strategy_types
.iter()
.min_by_key(|(angle, _)| ((angle - strategy.angle.grade_angle()).abs() * 1000.0) as i32)
.map(|(_, name)| *name)
.unwrap_or("Custom")
);
println!(" Expected Sharpe ratio: {:.2}", performance.mag);
println!(
" Market alignment: {:.2}",
performance.angle.grade_angle() / (PI / 2.0)
);
println!("\nBacktest results:");
println!(" Average return: {:.2}%", avg_return * 100.0);
println!(
" Annualized Sharpe ratio: {:.2}",
sharpe_ratio * (252.0_f64).sqrt()
);
println!(" Maximum drawdown: {:.2}%", max_drawdown * 100.0);
println!(" Backtest runtime: {}µs", duration.as_micros());
println!(
" Processing time per period: {}ns",
duration.as_nanos() / backtest_periods as u128
);
println!("\nOptimal strategy allocation across market regimes:");
for (i, weight) in average_weights.iter().enumerate() {
let strat_type = strategy_types
.iter()
.min_by_key(|(angle, _)| {
((angle - strategies[i].angle.grade_angle()).abs() * 1000.0) as i32
})
.map(|(_, name)| *name)
.unwrap_or("Custom");
println!(" {}: {:.1}%", strat_type, weight * 100.0);
}
}