spb/metrika Public
Stata-class statistics, GPU-accelerated by Apple Silicon. Native Swift — no Electron, no Python runtime, no compromises.
Swift 92.4%
HTML 3.3%
R 3%
Shell 1.3%
-
feat(stats): gradient-boosted regression trees (boost command)
…
- ZQGradientBoosting: exact-greedy trees cloning xgboost's algorithm — gain 1/2[GL2/(HL+l) + GR2/(HR+l) - G2/(H+l)] - gamma, leaf -G/(H+l), midpoint splits between consecutive distinct values, missing rows default left, pre-sorted feature indices; squared loss, deterministic (no subsampling) - engine: 'boost y x…, rounds(#) [eta() maxdepth() lambda()]' reporting training R2/RMSE with an in-sample caveat; model stored in the estimation state (Kind.boost) so predict routes through the trees (missing features follow the default direction); margins and GLM statistics refused after boost - validation: per-observation prediction parity with R xgboost 3.2 (exact method, base_score = mean) at 1e-4 (xgboost is float32 internally); a stump finds the exact midpoint split with lambda 0; training loss decreases monotonically in rounds - manual entry + coverage test - 115 tests green (swift test and xcodebuild with GPU suites) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
-
feat(stats): elastic net and lasso via coordinate descent
…
- ZQElasticNet: cyclic coordinate descent with residual updates, glmnet-convention objective ((1/2n)RSS + lambda(alpha*l1 + (1-alpha)/2*l2)), internal predictor standardization (1/n variance), unpenalized intercept, coefficients reported on the original scale; lambdaMax helper - matched glmnet's gaussian y-standardization quirk deliberately: the L1 penalty is invariant to it but the effective ridge penalty scales by 1/sd(y) — without this, alpha<1 fits diverge from glmnet by ~10% - engine: 'elasticnet y x…, lambda(#) [alpha(#)]' and 'lasso' (alpha fixed at 1); missing lambda() errors with the data's lambda_max as a hint; predict works afterwards, margins refuses (no VCE) - fixtures: glmnet 5.0 at thresh 1e-15 over deliberately correlated regressors; coefficients match at 1e-6 (documented tolerance for penalized iterative solvers) and the selection pattern (which coefficients are exactly zero) matches exactly - ZQCoefficient gains a public initializer - 104 tests green (swift test and xcodebuild with GPU suites) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
-
feat(engine): margins dydx() with delta-method standard errors
…
- ZQOLSResult/ZQGLMResult expose the full covariance matrix (column-major k x k aligned with coefficients); IV passes it through - EstimationState carries vce, inference df, and the estimation-sample design (GLMs only — AMEs need it) - margins, dydx(varlist): OLS/IV effects are the coefficients with their SEs; GLM average marginal effects with analytic delta gradients (logit p(1-p)(1-2p), probit -xb*phi, poisson exp) over the estimation sample; t or z inference per model kind - factor/interaction dydx rejected with a clear message (discrete-change margins later); continuous terms of factor models work - R fixtures mirror the exact formulas at the converged coefficients; logit/poisson AME and delta SE match at 1e-10 - 98 tests green (swift test and xcodebuild with GPU suites) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
-
feat(stats): xtreg fixed effects and ivregress 2sls
…
- parser: (endog = instruments) varlist groups -> ZQIVSpec; digit-led sub-commands (2sls) reassembled from number+identifier tokens via column adjacency - ZQFixedEffects: within estimator with Stata conventions (add-back means, reported _cons, df = N-K-G), within R-squared, panel-clustered VCE with G/(G-1) and t on G-1 df; v0.2 restriction: cluster variable must equal the panel variable - ZQIV: 2SLS via thin-Q projection of the instrument matrix (Z'Z never formed), residuals from original regressors, Stata 'small' inference, classical/HC1/cluster VCE built on projected regressors - engine: xtreg (requires xtset + fe), ivregress 2sls with dedicated listwise deletion across depvar/exog/endog/instruments; shared coefficient-table renderer extracted - fixtures: z1/z2 instrument columns (drawn after existing draws, earlier golden values bit-identical), manual within/2SLS algebra in R - 75 tests green (swift test and xcodebuild with GPU suites) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
-
feat(data): native Stata .dta reader (117-119) and writer (118)
…
- DTAReader: formats 117/118/119, both byte orders, all numeric storage types widened to Float64 with Stata missing codes (., .a-.z) mapped to the validity mask; str# and strL (GSO) load as strings; value labels read past but not yet applied; pre-117 files rejected with a clear message - DTAWriter: format 118 (UTF-8, LSF), doubles + str# up to 2045 bytes, real map offsets so Stata/haven/pandas can seek - ZQDataStore routes .dta through the native path for use and save - ZQColumnData equality now ignores value slots at missing positions (undefined by contract, often NaN — synthesized == failed on NaN != NaN) - Fixtures: haven-written 117 + 118 files; tests assert bit-identical numeric loads vs the CSV, lossless write/read roundtrip; haven cross-reads Metrika-written files (verified) - 61 tests green Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>