code wiki / (root) / nx_fin_metrics.nx

nx_fin_metrics.nx source

↩ module page · 52 lines · 2325 B

1// nx_fin_metrics.nx -- risk-adjusted performance metrics, i64 fixed-point, NO floats. Provides the integer 2// sqrt primitive (me_isqrt, Newton's method) the float-free runtime needs, then mean / standard-deviation / 3// SHARPE / downside-deviation / SORTINO over a returns array (per-period returns in basis points). Sharpe and 4// Sortino are returned in MILLI-units (x1000) for integer resolution. Risk-free / MAR passed in (default 0). 5// These are the numbers that grade an edge HONESTLY -- reward per unit of risk, not raw return. Pure; composes 6// with nx_fin_backtest's per-trade/per-period returns. license_tier: ORIGINAL 7import "nx_syscalls.nx" 8 9// floor(sqrt(n)) by Newton's method. n<=0 -> 0. 10func me_isqrt(n: i64) -> i64 { 11 if n <= 0 { return 0 } 12 var x: i64 = n 13 var y: i64 = (x + 1) / 2 14 while y < x { x = y; y = (x + n/x) / 2 } 15 return x 16} 17 18func me_sum(vals: *i64, n: i64) -> i64 { var s: i64 = 0; var i: i64 = 0; while i < n { s = s + vals[i]; i = i + 1 } return s } 19 20// mean of the returns (same units as input, e.g. bps) 21func me_mean(vals: *i64, n: i64) -> i64 { if n <= 0 { return 0 } return me_sum(vals, n) / n } 22 23// population standard deviation (same units as input) 24func me_stddev(vals: *i64, n: i64) -> i64 { 25 if n <= 0 { return 0 } 26 let mean: i64 = me_mean(vals, n) 27 var ss: i64 = 0; var i: i64 = 0 28 while i < n { let d: i64 = vals[i] - mean; ss = ss + d*d; i = i + 1 } 29 return me_isqrt(ss / n) 30} 31 32// Sharpe ratio x1000 = (mean - rf) / stddev. rf in same units as returns. sd==0 -> 0. 33func me_sharpe_milli(vals: *i64, n: i64, rf: i64) -> i64 { 34 let sd: i64 = me_stddev(vals, n) 35 if sd <= 0 { return 0 } 36 return (me_mean(vals, n) - rf) * 1000 / sd 37} 38 39// downside deviation vs a minimum-acceptable-return (mar); only returns below mar contribute; denominator = n. 40func me_downside_dev(vals: *i64, n: i64, mar: i64) -> i64 { 41 if n <= 0 { return 0 } 42 var ss: i64 = 0; var i: i64 = 0 43 while i < n { if vals[i] < mar { let d: i64 = vals[i] - mar; ss = ss + d*d } i = i + 1 } 44 return me_isqrt(ss / n) 45} 46 47// Sortino ratio x1000 = (mean - mar) / downside_dev. dd==0 -> 0. 48func me_sortino_milli(vals: *i64, n: i64, mar: i64) -> i64 { 49 let dd: i64 = me_downside_dev(vals, n, mar) 50 if dd <= 0 { return 0 } 51 return (me_mean(vals, n) - mar) * 1000 / dd 52}