Statistical Primitives

Foundation accumulators used by every higher-level kernel. SMA-seeded EMAs, numerically stable Welford variance, nearest-rank percentile rings, z-scores, crossover detection, and hysteresis gates.

ewmaAccumulator_c

SMA-seeded EMA. First period samples average into the seed; subsequent samples apply ema += 2/(period+1) × (value - ema). Returns false while seeding.

MethodPurpose
configure(period)Set EMA period
reset()Clear state
update(value, outResult)Feed sample; false while seeding
seeded()Seed complete flag
value()Current EMA

welfordAccumulator_c

One-pass running mean/variance/stddev. Numerically stable against catastrophic cancellation. Variance is sample estimator M2/(n-1); single-sample reads 0.

MethodPurpose
reset()Clear state
update(value)Feed one sample
count()Sample count
mean()Running mean
variance()Sample variance
stdDev()Sample standard deviation

percentileRing_c

Ring of newest capacity samples with nearest-rank percentile queries. Scratch buffer sorted in-place per query. Also provides fractionBelowOrEqual for rank queries.

MethodPurpose
configure(capacity)Allocate ring + scratch via st_malloc
reset()Clear samples
push(value)Add sample
percentile(p, outResult)Nearest-rank percentile [0,1]
fractionBelowOrEqual(value)Fraction of samples ≤ value

algoZScore

Free function: (value - mean) / sigma. Returns 0 when sigma ≤ 0 to prevent division-by-zero signals.

algoCrossOver

Detects UP/DOWN/NONE transitions between two series. Free function comparing previous and current values of A vs B.

algoHysteresisGate_c

N-consecutive-in / M-consecutive-out dwell logic. Prevents rapid state toggling at threshold boundaries. Configure enter/exit thresholds plus dwell counts.

Online Learning

In-process models that learn from live data without external services. Logistic regression with drift freeze, hidden Markov forward filter, conformal abstention, Bayesian change-point detection, recursive least squares, and extreme-value tail estimation.

algoOnlineLogistic_c

Decimal online logistic regression: Welford standardization, bounded SGD, L2 regularization, weight clipping. Up to 32 features. Optional drift-freeze monitor (fast/slow loss-EMA latch) and win-rate EMA tracker. JSON-serializable for restart persistence.

Config FieldDefaultPurpose
ui32FeatureCount0[1, 32]
decLearnRate0.03SGD step size
decL20.0001L2 regularization
decWeightClip20Weight bounds
fDriftMonitorfalseEnable drift freeze
fWinRateTrackerfalseEnable win-rate EMA
MethodPurpose
predict(features, count)Probability [1e-6, 1-1e-6]
train(features, count, label)One labelled sample {0,1}
onTradeOutcome(isWin)Feed closed-trade result
frozen()Drift freeze active
toJson() / fromJson()State persistence

algoOnlineLogisticEnsemble_c

Bagged ensemble of online logistic kernels behind one label stream. Each member trains only on its deterministic subsample (splitmix64 hash). Serves member predictions' mean and population std as an uncertainty readout: disagreement approximates prediction confidence without a held-out set. Restart-stable (fixed hash, exact persistence). Designed as a shadow/measurement layer — promote to serving only after the ensemble beats the primary model on live labels.

Config FieldDefaultPurpose
sKernel{}Member kernel configuration
ui32MemberCount5[1, 9]
decBagFraction0.63Per-member inclusion; 1.0 = no diversity
ui64Seedgolden ratioBag-hash seed; 0 = default
MethodPurpose
configure(config_s)Set geometry and kernel
train(features, count, label)One sample; members train per bag
predict(features, count)Mean/std/warm/ready
toJson() / fromJson()Exact member-state persistence

Prediction struct: decMean (warm members' mean), decStd (member disagreement), ui32WarmMembers, fReady (majority warm).

algoLinUcbBandit_c

Disjoint LinUCB contextual bandit (Li et al. 2010). One independent ridge model per arm: selection maximizes theta_a' x + alpha * sqrt( x' A_a^-1 x ); the acting arm's model folds the realized reward via A += x x', b += r x. select() never mutates state — the caller decides which arm acts and trains it through update(), making the class usable as a shadow policy (suggest on a decision, train on the outcome) as well as a served one. A starts at ridge * I (the prior), so a cold bandit is deterministic. Gauss-Jordan inversion with partial pivoting on a stack copy; feature counts stay small (≤ 16). Caller owns the context: arm semantics, feature scaling (aim for unit scale), and reward normalization.

Config FieldDefaultPurpose
ui32Arms0[0 or 2, 8]; < 2 leaves bandit inert
ui32Features0[1, 16]
decAlpha0.30Optimism weight on posterior std
decRidge1.0A prior diagonal; larger = slower learning
MethodPurpose
configure(config_s)Set geometry; resets to prior
select(context, count)Argmax UCB arm (pure, no state change)
update(arm, context, count, reward)Fold realized reward for acting arm
mean(arm, context, count)Posterior mean reward (no optimism)
toJson() / fromJson()Exact matrices; geometry mismatch rejects

algoHmm_c

Online hidden Markov forward filter. Up to 4 states, 8 observation dimensions. Diagonal Gaussian emissions learned online from posterior responsibilities. EWMA transition matrix updates converge from uniform prior — no training corpus needed.

MethodPurpose
init(stateCount, stayProb, ewmaAlpha)Scalar or array overload
reset()Clear state
update(observations, count)Feed vector; returns log-likelihood
posterior(state)Current posterior probability
argmaxState()Most likely state index

conformalGate_c

Split/Mondrian conformal abstention gate. Per-bucket residual rings calibrate a quantile. Entry admitted only when finite-sample lower bound on edge clears round-trip cost. Fixed double[6][400] rings.

MethodPurpose
init(alpha, minResiduals)Configure miscoverage
pushResidual(bucket, absResidual)Feed residual
admits(bucket, yHat, sigma, horizon, cost, theta)Admission decision struct

changePoint_c

Bayesian online change-point detection (BOCPD). Run-length posterior over Normal predictive model with constant hazard. Truncated at 600 run lengths. Fixed double[600] arrays.

MethodPurpose
init(hazardLambda, knownSigma, shortRunThreshold)Configure
update(observation)Returns break probability struct

valueHead_c

Recursive least squares with ridge regularization and exponential forgetting. Up to 32 features. Fixed double[32] + double[32×32].

MethodPurpose
init(dim, delta, gamma, ridge)Configure
predict(features)Linear prediction
update(features, target)One RLS step

tailIndex_c

Extreme-value fragility via peaks-over-threshold. Hill tail index, GPD scale, expected shortfall ES_99, z-scored fragility score against slow EWMA baseline. Fixed double[1800] ring.

MethodPurpose
push(absReturn)Ingest one absolute log-return
compute()Hill, ES99, fragility struct

algoPromotionPolicy_c

The evidence gate every learned layer passes before it is allowed to act. It consumes the layer's per-window outcome — the realized edge of the executed action and whether the challenger's suggestion agreed with it — keeps a rolling window of labelled outcomes only, and returns a verdict: COLD, INSUFFICIENT_EVIDENCE, HOLD, PROMOTE, DEMOTE. A window in which no round trip closed is not a label: its realized edge reads zero by construction (no trade), so a quiet stretch cannot masquerade as break-even evidence. This is the "measured over N labels" window the BASIN learning roadmap calls for.

Verdict rules: PROMOTE when challenger mean ≥ demoteEdgeBps and gain ≥ minEdgeGainBps and agreement ≥ minAgreeFrac. Advisory by contract: the class never mutates a policy — the operator makes serve an explicit config action.

Config FieldDefaultPurpose
ui32WindowSize256Rolling window length in labels (clamped to 512)
ui32MinLabels32Labels required before leaving COLD
ui32MinAgreeLabels16Agreeing labels required to compare
decMinAgreeFrac0.5Agreement-rate floor for meaningful comparison
decMinEdgeGainBps0Challenger gain over incumbent required to promote
decDemoteEdgeBps0Serving floor; below it the layer is demoted

Offline Learning & Model Training

Deterministic offline training core for the BASIN learning roadmap. Fits a linear logistic model or small tanh MLP with a k-fold time-series split, applies Platt scaling and/or Mondrian conformal calibration on out-of-fold predictions, and emits a versioned weight bundle. The same corpus and config always produce a byte-identical bundle — no wall clock, no random source beyond the seed, no threading.

algoOfflineTrainer_c

The orchestrator. configure() selects the model (LOGISTIC/MLP), the split (ui32Folds, ui32Gap), the MLP geometry and optimizer, the calibration mode and alpha, and the seed. train() consumes a corpus and returns a versioned weight bundle plus metrics.

Config FieldDefaultPurpose
eModelLOGISTICLOGISTIC or MLP
ui32Folds5K-fold count [1,32]
ui32Gap2Samples purged before each test block
eCalibrationPLATT_CONFORMALnone / platt / conformal / platt_conformal
decConformalAlpha0.1Coverage target (90% intervals)
ui64Seedgolden ratioSplitmix64 seed; same corpus + config → byte-identical bundle
MethodPurpose
configure(config_s)Select model, split, calibration, seed
train(corpus, outBundle, outReport)Fit model, calibrate, emit versioned bundle

algoWeightBundle_c

Plain data container plus inference. The trainer fills it; every consumer reads it. Serialized as one JSON object. Append-only rule: readers ignore unknown members, so a new optional member is an append-only change that keeps version == 1. A breaking layout change bumps ce_ui32Version; older readers reject an unknown version whole.

MethodPurpose
predict(features, count)Probability and conformal interval
contentHash()Stable FNV-1a fingerprint over model payload
toJson() / fromJson()Append-only state-file section

Weight Bundle Format v1

FieldNotes
standardizer.mean[F], standardizer.scale[F]Input normalization; scale 0 = constant
logistic.weights[F], logistic.interceptLinear head on standardized inputs
mlp.w1[H*F] (row-major), mlp.b1[H], mlp.w2[H], mlp.b2Tanh hidden head
calibration.conformal.counts[6], .quantiles[6]Mondrian cells: six equal-width probability bins
metrics.*Out-of-fold samples/folds, train+validation log-loss, Brier, AUC, accuracy, conformal coverage
Determinism Contract
Index-arithmetic splits, fixed fold order, splitmix64-seeded model init, fixed iteration/epoch count, closed-form / fixed-iteration calibration. Eigen is confined to the .cpp; features and labels enter as decimal_t, convert explicitly for the fit, and every weight/probability/metric returns through decimal_t::fromDouble. Two identical corpus+config runs produce a byte-identical bundle — the unit-suite contentHash() assertion verifies this.

Regime Detectors

All regime detectors implement algoRegimeDetector_c and produce algoRegimeResult_s with regime classification, signal quality, trend/volatility state, strength, confidence, and validity flag.

Shared Types (algoRegimeTypes.h)

TypeKindValues
algoMarketRegime_eenumUNKNOWN, TRENDING_UP, TRENDING_DOWN, RANGE_BOUND, HIGH_VOLATILITY, LOW_VOLATILITY, BREAKOUT, MEAN_REVERTING
algoSignalQuality_eenumNONE, WEAK, MODERATE, STRONG, VERY_STRONG
algoTrendState_eenumFLAT, UPTREND, DOWNTREND, TRANSITIONING
algoVolatilityState_eenumNORMAL, COMPRESSED, EXPANDING, ELEVATED
algoRegimeResult_sstructeRegime, eQuality, eTrend, eVolatility, decStrength, decConfidence, fValid

algoRegimeHmm_c

Wraps algoHmm_c and maps dominant state posterior to market regime. Configurable thresholds for trending vs range-bound classification. Ready after 30 steps minimum. Input: observation vectors up to 8 dimensions.

ConfigDefaultPurpose
i32StateCount3HMM states [2,4]
decStayProbability0.95Transition diagonal
decEwmaAlpha0.02Online learning rate
decTrendThreshold0.6Posterior ≥ this → trending
decRangeThreshold0.4Posterior < this → transitioning

algoRegimeAdx_c

Classic Wilder ADX/+DI/-DI over configurable period. Smoothed true range and directional movement. Classifies trending vs range-bound based on ADX thresholds. Input: OHLC bars.

ConfigDefault
ui32Period14 (max 256)
decTrendingThreshold25
decStrongTrendThreshold40
decRangeThreshold20

algoRegimeBollinger_c

Bollinger bandwidth and %B. Detects squeeze (low bandwidth → breakout imminent) and expansion (high bandwidth → elevated vol). Input: close prices.

ConfigDefault
ui32Period20 (max 512)
decBandWidth2
decSqueezeThreshold0.005
decExpansionThreshold0.03

algoRegimeVolCluster_c

Short-window vs long-window realized vol ratio. Expansion above threshold → HIGH_VOLATILITY; compression below → LOW_VOLATILITY. Newton's method integer sqrt. Input: per-bar returns.

ConfigDefault
ui32ShortWindow10
ui32LongWindow100 (max 512)
decExpansionRatio1.5
decCompressionRatio0.7

algoRegimeCvd_c

Rolling correlation between CVD delta and price changes. Positive correlation → trending (accumulation/distribution confirms price). Negative or diverging → mean-reverting signal. Tracks cumulative CVD. Input: paired CVD delta + price change per bar.

ConfigDefaultPurpose
ui32Window50 (max 512)Rolling correlation window
decAccumulationThreshold0.3Corr > this → TRENDING_UP
decDistributionThreshold-0.3Corr < this → TRENDING_DOWN
decDivergenceThreshold0.5|corr| < this with large CVD → MEAN_REVERTING

Strength Calculators

All strength calculators implement algoRegimeStrength_c and produce a normalized decimal_t strength [0,1] plus an algoSignalQuality_e mapping.

algoCompositeStrength_c

Combines up to 8 weighted source strengths into a single composite. Clamped to [0,1]. Quality mapped through configurable thresholds.

ConfigDefaultPurpose
ui32SourceCount0 (max 8)Number of sources
arrWeights{}Per-source weight
decStrongThreshold0.7→ STRONG
decModerateThreshold0.4→ MODERATE
decWeakThreshold0.2→ WEAK
MethodPurpose
setSource(index, value)Set one source strength
compute()Calculate weighted composite
strength()Last computed composite
quality()Threshold-mapped quality

algoTrendConviction_c

Fast/slow EMA spread in bps plus consecutive-bar persistence tracking. Strength blends normalized absolute spread and consecutive-bar count. Spread below minimum yields zero.

ConfigDefault
ui32EmaFastPeriod5
ui32EmaSlowPeriod20
ui32ConsecutiveBars3
decMinSpreadBps5

Outputs: strength() [0,1], quality(), trendState() (FLAT/UPTREND/DOWNTREND/TRANSITIONING), emaSpread() raw bps.

algoVolNormalization_c

Current vol as ratio of Welford running mean. Drives both strength output and discrete volatility state classification (NORMAL/COMPRESSED/EXPANDING/ELEVATED).

ConfigDefault
ui32Lookback100
decLowVolThreshold0.5 (≤ → COMPRESSED)
decHighVolThreshold1.5 (≥ → EXPANDING)
decExtremeVolThreshold2.5 (≥ → ELEVATED)

algoFlowImbalance_c

Buy/sell imbalance as signed-flow / total-flow over a trailing window via algoSignedFlowBuckets_c. Feed from onMarketdataTick, read in onMarketdataOhlcClose.

ConfigDefault
ui32BucketCount60
ui64BucketDurationMs1000
ui64WindowMs30000
decStrongThreshold0.6
decModerateThreshold0.3

Market Data Analytics

On-demand candle analytics and signed-flow accumulation. Not indicator plugins — stateless pure functions and bucket rings with zero per-bar cost when unused.

Candle Analytics (free functions)

On-demand pure functions over the candle ring. Zero per-bar cost when unused. Header-only.

FunctionPurpose
candleCvdDelta(candle)Single-bar signed flow from taker aggressor split
candleCvdWindow(ohlc, sequence, bars)Dense-window CVD delta + volume over N bars
candleCvdAnchored(ohlc, sequence)Ring-lifetime cumulative CVD from oldest retained bar
candleHeikinAshiWindow(ohlc, sequence, out, bars)HA transform in offset order, seeded at window's oldest bar

algoSignedFlowBuckets_c

Ring of fixed-duration time buckets accumulating signed and total flow. Stale buckets zero out of window queries automatically. Covers per-bar, 1s notional, and accumulator patterns.

MethodPurpose
configure(bucketCount, bucketDurationMs)Allocate ring via st_malloc
onTrade(signed, total, nowMs)Stamp trade into bucket
windowSigned(windowMs)Sum signed over window
windowTotal(windowMs)Sum total over window
windowSums(windowMs, outSigned, outTotal)Combined single-walk

Cross-Asset Engines

Multi-asset covariance, lead/lag transmission, Mahalanobis turbulence, and synchronous BBO resampling for cross-venue strategies.

algoCrossAssetEngine_c

EWMA covariance + dominant eigenfactor extraction for up to 8 assets. Reports per-asset loading, sigma, and lagging score relative to common factor. Fixed decimal_t[8][8] arrays.

MethodPurpose
init(assetCount, ewmaAlpha)Configure
update(returns, count)Ingest return vector
compute()Recompute eigenfactor
laggingScore(asset)(factor × loading − return) / sigma
dominantShare()λ[0] / Σλ

algoXCorrLeadLag_c

Rolling cross-correlation at configurable lags between two return series. Transmission score is max_tau rho(tau) signed by lead return at winning lag. Fixed decimal_t[256] rings.

MethodPurpose
init(window, maxLag)Configure
update(leadReturn, lagReturn)Push paired observation
bestLag()Winning lag index
score()max(rho) × sign(lead at best lag)

algoTurbulence_c

Mahalanobis turbulence index via EWMA mean/covariance + eigendecomposition. Static variance-ratio helper. Fixed decimal_t[8][8] arrays.

MethodPurpose
init(dim, ewmaAlpha)Configure
update(values, count)Ingest observation vector
turbulence()Mahalanobis distance
volRatio(shortVar, longVar)Static; ≥ 1 means expansion

algoVenueGrid_c

Synchronous BBO resampling grid for cross-venue strategies. Each venue pushes latest BBO; per grid step strategy reads one snapshot where every venue is represented by its most recent pre-grid quote. Fixed algoGridQuote_s[8].

MethodPurpose
init(venueCount, gridMs)Configure
update(venue, quote)Ingest BBO sample
snapshot(now, maxStaleMs, out)Write quotes; returns fresh count

Numerical Primitives

Low-level mathematical building blocks: eigensolver, rough-path signatures, and optimal transport displacement profiles.

algoEig_c

Fixed-capacity symmetric Jacobi eigensolver (up to 8×8). Solver internals in double; API boundary in decimal_t. Caller-provided output arrays.

MethodPurpose
solve(matrix, dim, outEigenvalues, outEigenvectors)A = V·diag(λ)·Vᵀ
dominantShare(eigenvalues, dim)λ[0] / Σλ
reconstruct(eigenvalues, eigenvectors, dim, out)Rebuild A
reconstructionError(...)Accuracy metric

pathSignature_c

Truncated path log-signature (rough-path theory). Chen recursion levels 1–3 on up to 3 channels, projected onto 14 Lyndon words. Accumulation in double.

MethodPurpose
pushSegment(increment, channelCount)Append piecewise-linear segment
logSignature(out[14])14-word log-signature
levyArea(i, j)Antisymmetric area component
combine(left, right)Chen concatenation

ladderTransport_c

Quantile-displacement profile comparing book snapshots. Evaluates D0 (centroid), D1 (slope), D2 (curvature), W1 (Wasserstein cost), Λ (mass log-ratio) at 7 quantile levels over up to 20 price levels per side.

MethodPurpose
compute(prevBook, curBook, tick)Full displacement profile struct
Architecture: Signal Layer Composition
Kernels compose hierarchically. A typical production algo chains: signed flow buckets feed into flow imbalance strength; Welford accumulators feed into vol normalization; HMM feeds into regime HMM detector; all strengths merge through composite strength which gates entry alongside cost model admission and risk kernel approval before reaching the sizing stack. Every link is a separate, tested class — swap any component without touching the rest.