code wiki / (root) / nx_fin_strategy_gate.nx

nx_fin_strategy_gate.nx source

↩ module page · 72 lines · 4013 B

1// nx_fin_strategy_gate.nx -- R3 GATE: proves the SMA signal generator on known bars, then runs the FULL LOOP 2// R1(md_parse_csv) -> R3(st_sma_cross) -> R2(bt_run) end-to-end. The crossover buys into a top on this fixture 3// and takes a loss -> the loop HONESTLY reports a losing strategy (that is the whole point of the truth engine). 4// Exits 0 iff all pass. license_tier: ORIGINAL 5import "nx_gate.nx" 6import "nx_fin_marketdata.nx" 7import "nx_fin_backtest.nx" 8import "nx_fin_strategy.nx" 9 10func chk(name: *u8, got: i64, want: i64, st: *i64) -> i64 { 11 if got == want { st[0] = st[0] + 1; gw(" PASS " as *u8); gw(name); gw("\n" as *u8) } 12 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) } 13 return 0 14} 15 16func main() -> i64 { 17 let st: *i64 = sys_mmap(16) as *i64 18 st[0] = 0; st[1] = 0 19 20 let csv: *u8 = "Date,Open,High,Low,Close,Volume\n2024-01-02,10.00,10.00,10.00,10.00,1000000\n2024-01-03,11.00,11.00,11.00,11.00,1000000\n2024-01-04,10.50,10.50,10.50,10.50,1000000\n2024-01-05,12.00,12.00,12.00,12.00,1000000\n2024-01-06,11.50,11.50,11.50,11.50,1000000\n" as *u8 21 var n: i64 = 0; while csv[n] != (0 as u8) { n = n + 1 } 22 let bars: *i64 = sys_mmap(8 * MD_FIELDS * 16) as *i64 23 let nbars: i64 = md_parse_csv(csv, n, bars, 16) 24 chk("parsed 5 bars" as *u8, nbars, 5, st) 25 26 // -- SMA values (closes 1000,1100,1050,1200,1150) -- 27 chk("sma(end=2,p=2) = 1075" as *u8, st_sma(bars, 2, 2), 1075, st) 28 chk("sma(end=2,p=3) = 1050" as *u8, st_sma(bars, 2, 3), 1050, st) 29 chk("sma(end=3,p=2) = 1125" as *u8, st_sma(bars, 3, 2), 1125, st) 30 chk("sma(end=3,p=3) = 1116" as *u8, st_sma(bars, 3, 3), 1116, st) 31 chk("sma no-history (end=0,p=3) = 0" as *u8, st_sma(bars, 0, 3), 0, st) 32 33 // -- signals: fast=2, slow=3, decided through bar i-1 (no look-ahead) -- 34 let sig: *i64 = sys_mmap(8 * 8) as *i64 35 st_sma_cross(bars, nbars, 2, 3, sig) 36 chk("signal[0] = 0 (no history)" as *u8, sig[0], 0, st) 37 chk("signal[2] = 0 (no history)" as *u8, sig[2], 0, st) 38 chk("signal[3] = 1 (fast>slow)" as *u8, sig[3], 1, st) 39 chk("signal[4] = 1 (fast>slow)" as *u8, sig[4], 1, st) 40 41 // -- FULL LOOP: R3 signals -> R2 backtester -- 42 let out: *i64 = sys_mmap(8 * 16) as *i64 43 bt_run(bars, nbars, sig, 1000000, 0, 0, 0, 0, out) 44 chk("loop n_trades = 1" as *u8, out[BT_TRADES], 1, st) 45 chk("loop n_losses = 1 (HONEST: strategy lost)" as *u8, out[BT_LOSSES], 1, st) 46 chk("loop net_pnl = -41650 cents" as *u8, out[BT_NET], 0 - 41650, st) 47 chk("loop final_equity = 958350 cents" as *u8, out[BT_FINAL_EQ], 958350, st) 48 49 // momentum (above SMA) / mean-reversion (below SMA), period 2, decided through bar i-1 50 let sig2: *i64 = sys_mmap(8 * 8) as *i64 51 st_above_sma(bars, nbars, 2, sig2) 52 chk("above_sma[2]=1 (1100>sma1050)" as *u8, sig2[2], 1, st) 53 chk("above_sma[3]=0 (1050<sma1075)" as *u8, sig2[3], 0, st) 54 chk("above_sma[4]=1 (1200>sma1125)" as *u8, sig2[4], 1, st) 55 let sig3: *i64 = sys_mmap(8 * 8) as *i64 56 st_below_sma(bars, nbars, 2, sig3) 57 chk("below_sma[3]=1 (1050<sma1075)" as *u8, sig3[3], 1, st) 58 chk("below_sma[4]=0 (1200>sma1125)" as *u8, sig3[4], 0, st) 59 60 // Donchian breakout: highest-close over the prior window; long on a break above it 61 chk("donchian_high(end=1,p=2) = 1100" as *u8, st_donchian_high(bars, 1, 2), 1100, st) 62 chk("donchian_high(end=3,p=2) = 1200" as *u8, st_donchian_high(bars, 3, 2), 1200, st) 63 let sig4: *i64 = sys_mmap(8 * 8) as *i64 64 st_donchian_signal(bars, nbars, 2, sig4) 65 chk("donchian[3]=0 (1050 < prior-high 1100)" as *u8, sig4[3], 0, st) 66 chk("donchian[4]=1 (1200 > prior-high 1100 = breakout)" as *u8, sig4[4], 1, st) 67 68 gw("nx_fin_strategy_gate: PASS=" as *u8); gn(st[0]); gw(" FAIL=" as *u8); gn(st[1]); gw("\n" as *u8) 69 if st[1] == 0 { gw("R3 nx_fin_strategy: GREEN (full R1->R3->R2 loop proven)\n" as *u8); return 0 } 70 gw("R3 nx_fin_strategy: RED\n" as *u8) 71 return 1 72}