code wiki / (root) / nx_fin_zscore.nx

nx_fin_zscore.nx source

↩ module page · 41 lines · 2416 B

1// nx_fin_zscore.nx -- R-MKT1 of the MARKETS-INVESTING finance arc: the ALTMAN Z-SCORE, a distress/bankruptcy 2// predictor that answers "is this company financially healthy or in trouble?" from its balance sheet + income 3// statement (the numbers you pull from an EDGAR 10-K). Grounded in the Nishi researcher's fetched source 4// knowledge/fetched/fin_val_altman.raw (Altman 1968, public manufacturers): 5// Z = 1.2*X1 + 1.4*X2 + 3.3*X3 + 0.6*X4 + 1.0*X5 6// X1 = working capital / total assets (short-term liquidity) 7// X2 = retained earnings / total assets (cumulative profitability / age) 8// X3 = EBIT / total assets (operating productivity) 9// X4 = market value of equity / total liabs (solvency cushion) 10// X5 = sales / total assets (asset turnover) 11// Zones: Z > 2.99 SAFE | 1.81..2.99 GREY | Z < 1.81 DISTRESS. 12// NO FLOATS: ratios are scaled x1000 (Xi_s = num*1000/den), coefficients x10 (12/14/33/6/10), the final 13// /10 returns Z scaled x1000 -- exact integer arithmetic, the only correct way to do money. Thresholds are 14// DATA (#11). Pure function, no store, no hardware writes -- safe to run in any request path. license_tier: ORIGINAL 15import "nx_syscalls.nx" 16const AZ_MAGIC_2990: i64 = 2990 17const AZ_MAGIC_1810: i64 = 1810 18 19const AZ_DISTRESS: i64 = 0 20const AZ_GREY: i64 = 1 21const AZ_SAFE: i64 = 2 22 23// Altman Z-score x1000 from raw figures (consistent monetary units -- $thousands, $, or cents, any, as long as 24// all seven are the same unit). Returns Z*1000. total_assets==0 -> 0 (no data -> treated as distress by az_zone). 25func az_zscore(working_capital: i64, retained_earnings: i64, ebit: i64, mv_equity: i64, total_liabilities: i64, sales: i64, total_assets: i64) -> i64 { 26 if total_assets == 0 { return 0 } 27 let x1: i64 = working_capital * 1000 / total_assets 28 let x2: i64 = retained_earnings * 1000 / total_assets 29 let x3: i64 = ebit * 1000 / total_assets 30 var x4: i64 = 0 31 if total_liabilities != 0 { x4 = mv_equity * 1000 / total_liabilities } 32 let x5: i64 = sales * 1000 / total_assets 33 return (12 * x1 + 14 * x2 + 33 * x3 + 6 * x4 + 10 * x5) / 10 34} 35 36// classify a x1000 Z-score into a zone. Thresholds = DATA (2.99 / 1.81, scaled x1000). 37func az_zone(z1000: i64) -> i64 { 38 if z1000 > AZ_MAGIC_2990 { return AZ_SAFE } 39 if z1000 >= AZ_MAGIC_1810 { return AZ_GREY } 40 return AZ_DISTRESS 41}