Metrika
Stata-class statistics, GPU-accelerated by Apple Silicon. Native Swift. No Electron. No Python runtime. No compromises.
One session: a cluster-robust factor-variable regression, then a
10,000-replicate pairs bootstrap — batched on the Apple GPU, exactly
reproducible from seed(42) on any backend.
Why Metrika
- One line, publication-ready output.
reg log_rev price i.region, cluster(firm_id)— the Stata mental model, with factor variables,if/inqualifiers, robust and cluster-robust inference. - The GPU is invisible. A planner dispatches every command to CPU (LAPACK) or GPU (MLX) automatically. Large bootstrap runs execute as batched Metal solves; you never choose a backend.
- Reproducibility is a feature, not an accident. All randomness flows through a counter-based Philox4x32 generator:
set seed 42produces bit-identical resamples on CPU and GPU, in any chunk order, across any parallelism. - Numbers you can defend. Every CPU estimator is validated against R to 1e-10 relative tolerance — coefficients, standard errors (classical, HC0–HC3, cluster), p-values, marginal effects. Penalized and boosted models cross-validate against glmnet and xgboost.
- Big data on a laptop. DuckDB columnar engine with bulk C-API extraction: 10 million rows load in 0.2 s, summarize in ~0.3 s, regress in ~0.2 s. A Metal point-sprite renderer takes over scatter plots past 100k points and shrugs at 2,000,000.
Screenshots
Swift Charts with by() groups![]() |
2,000,000 points — Metal renderer![]() |
Virtualized data browser with expression filter![]() |
Built-in manual for all 38 commands![]() |
Install
Download Metrika.dmg — signed, notarized, and stapled. Drag into Applications. macOS 14+ on Apple Silicon.
A five-minute tour
. sysuse sales // bundled 200-firm × 5-year panel
. gen log_rev = ln(revenue)
. summarize revenue price, detail
. reg log_rev price i.region, robust // HC1 SEs, factor expansion
. predict yhat
. margins, dydx(price) // delta-method standard errors
. xtset firm_id
. xtreg log_rev price, fe cluster(firm_id)
. ivregress 2sls log_rev (price = z1 z2), robust
. logit purchase price
. margins, dydx(price)
. bootstrap, reps(100000) seed(42): reg log_rev price // GPU batched
. permute, reps(10000) seed(42): reg log_rev price // exact p-values
. bayes, mcmcsize(20000) seed(42): reg log_rev price // Gibbs sampler
. lasso log_rev price z1 z2 orders, lambda(0.05) // glmnet-exact
. boost log_rev z1 z2 orders, rounds(100) maxdepth(3) // xgboost-exact
. scatter log_rev price, by(region)
. histogram revenue, bins(20)
. save results.dta, replace // native Stata .dta 118Everything above works identically in the console, in .zyq do-files
(⌘R in the editor), and headlessly through metrika-cli.
What's inside
| Pillar | Contents |
|---|---|
| Data | parquet, csv, json, arrow, native Stata .dta (read 117–119, write 118) · DuckDB engine · explicit missing-value semantics with listwise-deletion reporting |
| Estimation | OLS (QR, never X'X) · logit / probit / poisson · 2SLS · panel fixed effects · summarize / tabulate / correlate |
| Inference | robust HC0–HC3 · cluster-robust with Stata small-sample factors · GPU pairs bootstrap · permutation tests · Bayesian regression (Gibbs) |
| Machine learning | lasso & elastic net (coordinate descent, glmnet-exact) · gradient-boosted trees (xgboost-exact) |
| Post-estimation | predict (xb, residuals, pr, n) · margins, dydx() with delta-method SEs |
| Graphics | Swift Charts scatter/line/histogram/kdensity · Metal renderer for millions of points |
| Extensibility | .zyq script commands with args macros · native Swift ZQCommandPlugins with syntax validation and mutation gating |
Numerical validation
Metrika's test suite doesn't check that code runs — it checks that the numbers are right:
- 116 tests compare against golden values generated by R (
Tests/Fixtures/generate.R): OLS coefficients, every SE variant, t/F/χ² p-values into the far tails (p = 4×10⁻²² matches R exactly), GLM likelihoods, marginal effects and their delta-method SEs — all at 1e-10 relative tolerance. - Lasso/elastic-net coefficients match glmnet (including its subtle gaussian y-standardization convention); the selection pattern — which coefficients are exactly zero — matches exactly.
- Boosted-tree predictions match xgboost observation-by-observation.
- The GPU bootstrap's resample indices are asserted bit-identical to the CPU Philox reference; Philox itself is pinned to the Random123 known-answer vectors.
- With diffuse priors, the Bayesian posterior reproduces the frequentist answer within Monte-Carlo error — asserted, not assumed.
Architecture
┌─────────────────────────────────────────────────────────┐
│ Metrika (SwiftUI) │
│ Console · Data browser · Do-file editor · Manual │
└──────────────────────────┬──────────────────────────────┘
│
┌──────────────────────────▼──────────────────────────────┐
│ MetrikaKit (Swift package) │
│ │
│ ZQParser command grammar → typed AST │
│ ZQPlanner AST → CPU / GPU / hybrid dispatch │
│ ZQEngine sessions, execution, logging, help │
│ ZQData DataFrame façade over DuckDB + .dta │
│ ZQStats LAPACK estimators (Accelerate) │
│ ZQGPU MLX batched solves, Philox RNG │
│ ZQGraphics plot specs → Swift Charts / Metal │
│ ZQPlugins user commands & sandboxing │
└──────────────────────────────────────────────────────────┘MetrikaKit has zero UI dependencies and is fully testable with
swift test. ZQGPU is the only module allowed to touch MLX/Metal;
ZQStats the only one touching Accelerate — backends stay swappable.
Building from source
git clone https://github.com/spboucher-ai/metrika && cd metrika
./scripts/install_hooks.sh
# Library + CLI + tests
cd MetrikaKit
swift build && swift test # 116 tests (GPU suites auto-skip)
xcodebuild test -scheme MetrikaKit-Package \
-destination 'platform=macOS' -skipPackagePluginValidation # + GPU suites
# App
cd .. && xcodegen generate
xcodebuild -project Metrika.xcodeproj -scheme Metrika \
-skipPackagePluginValidation build
# Signed, notarized DMG
./scripts/release.shSwiftPM's CLI cannot compile Metal shaders, so
swift testskips the GPU suites and CLI builds fall back to CPU automatically;xcodebuildruns give you everything.
Documentation
- In the app: the Manual tab, or
help <command>in the console. - Static site:
docs/index.html— regenerated from the same registry bymetrika-cli docs, so it can never drift from the app.
Extending Metrika
Drop a .zyq script into ~/Library/Application Support/Metrika/Commands/:
// logreg.zyq — its filename becomes the command
args response predictor
gen __log = ln(`response')
reg __log `predictor', robust
drop __log…or compile a Swift plugin into the app:
public struct ZScorePlugin: ZQCommandPlugin {
public static let verb = "zscore"
public static let syntax = ZQSyntaxSpec(mutates: true)
public func execute(_ ctx: ZQContext) async throws -> ZQResult { … }
}Plugins that shadow built-ins are rejected at startup; datasets can only be mutated through a declared, gated channel.
© 2026 Simon-Pierre Boucher. All rights reserved. contact@spboucher.ai



