\begin{figure}[t] \centering \begin{tikzpicture}[ font=\sffamily\scriptsize, node distance=3mm, layer/.style={draw=black!70, line width=0.4pt, rounded corners=1.5pt, fill=black!3, text width=0.93\textwidth, align=left, inner sep=4pt}, tag/.style={font=\sffamily\bfseries\scriptsize, text=black!80}, arr/.style={-{Latex[length=1.6mm]}, line width=0.5pt, black!70}] \node[layer, fill=black!8] (py) {\textbf{Python (nanobind, GIL released)} \quad \texttt{raid.api}: ols $\cdot$ realized\_measures $\cdot$ har\_fit / har\_rolling / har\_batch $\cdot$ garch\_fit $\cdot$ bootstrap $\cdot$ var\_connectedness \quad \texttt{raid.findata}: bars $\cdot$ export $\cdot$ catalog \hfill \textbf{CLI} \texttt{raid devices $|$ validate $|$ estimate $|$ data}}; \node[layer, below=of py] (est) {\textbf{Estimators and models} \quad reductions (Neumaier, pairwise, Welford) $\cdot$ rolling windows $\cdot$ covariance (classical, HC0--HC3, HAC, cluster) $\cdot$ OLS/WLS/ridge $\cdot$ realized measures (RV, BPV, RSV$^\pm$, RQ, $J$, TriPV, RCov) $\cdot$ HAR family $\cdot$ GARCH family (QML) $\cdot$ block bootstrap $\cdot$ VAR, GFEVD, Diebold--Yilmaz, Ledoit--Wolf}; \node[layer, below=of est] (data) {\textbf{Data} \quad MarketCalendar (XNYS rules, DST, early closes) $\cdot$ BarSeries $+$ QualityReport $\cdot$ session-aware returns $\cdot$ calendar-aware aggregation $\cdot$ Parquet / Arrow IPC reader (column projection) $\cdot$ FinData client (bearer key, token bucket, retries, cursors, exports, checksummed cache, provenance)}; \node[layer, below=of data] (be) {\textbf{Backend contract} \quad Batch $=$ values $+$ CSR offsets $\;\longrightarrow\;$ sum\_squares $\cdot$ sum\_abs\_adjacent $\cdot$ semivariances $\cdot$ sum\_fourth $\cdot$ rolling\_sum\_squares $\cdot$ regression\_stats ($X'X$, $X'y$, $y'y$) $\cdot$ garch\_nll\_batch}; \node[draw=black!70, line width=0.4pt, rounded corners=1.5pt, fill=white, anchor=north west, text width=0.445\textwidth, align=left, inner sep=4pt] (cpu) at ($(be.south west)+(0,-3mm)$) {\textbf{CpuBackend} --- FP64, Neumaier per segment, parallel over segments, deterministic order}; \node[draw=black!70, line width=0.4pt, rounded corners=1.5pt, fill=red!4, anchor=north east, text width=0.445\textwidth, align=left, inner sep=4pt] (metal) at ($(be.south east)+(0,-3mm)$) {\textbf{MetalBackend} --- FP32 double-float (TwoSum), 4\,096-element chunks, tree reductions, FP64 combine on the host; prebuilt metallib or runtime MSL; buffer pool}; \node[layer, anchor=north west] (core) at ($(cpu.south west)+(0,-3mm)$) {\textbf{Core} \quad strong types (Timestamp $\mu$s UTC, Date, Interval) $\cdot$ RaidError $\cdot$ structured log with redaction $\cdot$ counter-seeded RNG streams $\cdot$ ThreadPool $\cdot$ SHA-256 $\cdot$ Estimate / InferenceResult / Convergence / Provenance $\cdot$ ExecutionPlan (auto$\,|\,$cpu$\,|\,$metal, PrecisionPolicy) $\cdot$ ExperimentManifest}; \draw[arr] (py.south) -- (est.north); \draw[arr] (est.south) -- (data.north); \draw[arr] (data.south) -- (be.north); \draw[arr] (be.south -| cpu.north) -- (cpu.north); \draw[arr] (be.south -| metal.north) -- (metal.north); \draw[arr, dashed] (metal.west |- cpu.east) -- node[above, font=\sffamily\tiny]{fallback} (cpu.east); \end{tikzpicture} \caption{Layers of \raid{}. Estimators consume the backend contract through an \texttt{ExecutionPlan}; every result is an \texttt{Estimate} that carries coefficients, loss, inference, convergence, warnings, runtime, backend, precision and provenance. The Metal backend falls back to the CPU backend when no device is available or a case is unsupported.} \label{fig:arch} \end{figure}