code wiki / (root) / nx_fin_portfolio_gate.nx

nx_fin_portfolio_gate.nx source

↩ module page · 51 lines · 2782 B

1// nx_fin_portfolio_gate.nx -- GATE for portfolio construction: equal/score weighting with concentration caps, 2// sector + total-exposure limits, and the Herfindahl diversification index, all hand-computed. Exits 0 iff all 3// pass. license_tier: ORIGINAL 4import "nx_gate.nx" 5import "nx_fin_portfolio.nx" 6 7func chk(name: *u8, got: i64, want: i64, st: *i64) -> i64 { 8 if got == want { st[0] = st[0] + 1; gw(" PASS " as *u8); gw(name); gw("\n" as *u8) } 9 else { st[1] = st[1] + 1; gw(" FAIL " as *u8); gw(name); gw(" got=" as *u8); gn(got); gw(" want=" as *u8); gn(want); gw("\n" as *u8) } 10 return 0 11} 12 13func main() -> i64 { 14 let st: *i64 = sys_mmap(16) as *i64 15 st[0] = 0; st[1] = 0 16 17 // equity $10,000 (1,000,000c), per-name cap 30% (3000 bps) 18 chk("equal-weight 5 names -> $2000 (20%)" as *u8, pf_equal_weight(1000000, 5, 3000), 200000, st) 19 chk("equal-weight 2 names -> capped at 30%" as *u8, pf_equal_weight(1000000, 2, 3000), 300000, st) 20 chk("equal-weight 0 -> 0" as *u8, pf_equal_weight(1000000, 0, 3000), 0, st) 21 22 chk("score-weight 300/1000 -> $3000" as *u8, pf_score_weight(1000000, 300, 1000, 3000), 300000, st) 23 chk("score-weight 500/1000 -> capped 30%" as *u8, pf_score_weight(1000000, 500, 1000, 3000), 300000, st) 24 chk("score-weight 100/1000 -> $1000" as *u8, pf_score_weight(1000000, 100, 1000, 3000), 100000, st) 25 26 chk("concentration 20% ok" as *u8, pf_concentration_ok(200000, 1000000, 3000), 1, st) 27 chk("concentration 40% > 30% -> no" as *u8, pf_concentration_ok(400000, 1000000, 3000), 0, st) 28 29 // sector cap 40% (4000 bps) 30 chk("sector 20%+15% <= 40% ok" as *u8, pf_sector_ok(200000, 150000, 1000000, 4000), 1, st) 31 chk("sector 30%+15% > 40% -> no" as *u8, pf_sector_ok(300000, 150000, 1000000, 4000), 0, st) 32 33 chk("total exposure 95% ok (no leverage)" as *u8, pf_total_exposure_ok(800000, 150000, 1000000), 1, st) 34 chk("total exposure 105% -> no leverage" as *u8, pf_total_exposure_ok(900000, 150000, 1000000), 0, st) 35 36 // Herfindahl: 5 equal-weight -> 2000 ; 2 names -> 5000 ; 1 name -> 10000 37 let w5: *i64 = sys_mmap(8 * 8) as *i64 38 w5[0]=2000; w5[1]=2000; w5[2]=2000; w5[3]=2000; w5[4]=2000 39 chk("HHI 5 equal = 2000 (10000/5)" as *u8, pf_herfindahl(w5, 5), 2000, st) 40 let w2: *i64 = sys_mmap(8 * 4) as *i64 41 w2[0]=5000; w2[1]=5000 42 chk("HHI 2 equal = 5000" as *u8, pf_herfindahl(w2, 2), 5000, st) 43 let w1: *i64 = sys_mmap(8 * 2) as *i64 44 w1[0]=10000 45 chk("HHI 1 name = 10000 (max concentration)" as *u8, pf_herfindahl(w1, 1), 10000, st) 46 47 gw("nx_fin_portfolio_gate: PASS=" as *u8); gn(st[0]); gw(" FAIL=" as *u8); gn(st[1]); gw("\n" as *u8) 48 if st[1] == 0 { gw("nx_fin_portfolio: GREEN\n" as *u8); return 0 } 49 gw("nx_fin_portfolio: RED\n" as *u8) 50 return 1 51}