Statistical engines, online-learning models, regime detectors, cross-asset analytics, and numerical
primitives that power ttTrader's signal layer. All kernels live in ttAlgoShared, computed
in decimal_t, with fixed-capacity allocation — no heap traffic on the update path.
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_cSMA-seeded EMA. First period samples average into the seed; subsequent samples apply ema += 2/(period+1) × (value - ema). Returns false while seeding.
| Method | Purpose |
|---|---|
configure(period) | Set EMA period |
reset() | Clear state |
update(value, outResult) | Feed sample; false while seeding |
seeded() | Seed complete flag |
value() | Current EMA |
welfordAccumulator_cOne-pass running mean/variance/stddev. Numerically stable against catastrophic cancellation. Variance is sample estimator M2/(n-1); single-sample reads 0.
| Method | Purpose |
|---|---|
reset() | Clear state |
update(value) | Feed one sample |
count() | Sample count |
mean() | Running mean |
variance() | Sample variance |
stdDev() | Sample standard deviation |
percentileRing_cRing of newest capacity samples with nearest-rank percentile queries. Scratch buffer sorted in-place per query. Also provides fractionBelowOrEqual for rank queries.
| Method | Purpose |
|---|---|
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 |
algoZScoreFree function: (value - mean) / sigma. Returns 0 when sigma ≤ 0 to prevent division-by-zero signals.
algoCrossOverDetects UP/DOWN/NONE transitions between two series. Free function comparing previous and current values of A vs B.
algoHysteresisGate_cN-consecutive-in / M-consecutive-out dwell logic. Prevents rapid state toggling at threshold boundaries. Configure enter/exit thresholds plus dwell counts.
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_cDecimal 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 Field | Default | Purpose |
|---|---|---|
ui32FeatureCount | 0 | [1, 32] |
decLearnRate | 0.03 | SGD step size |
decL2 | 0.0001 | L2 regularization |
decWeightClip | 20 | Weight bounds |
fDriftMonitor | false | Enable drift freeze |
fWinRateTracker | false | Enable win-rate EMA |
| Method | Purpose |
|---|---|
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_cBagged 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 Field | Default | Purpose |
|---|---|---|
sKernel | {} | Member kernel configuration |
ui32MemberCount | 5 | [1, 9] |
decBagFraction | 0.63 | Per-member inclusion; 1.0 = no diversity |
ui64Seed | golden ratio | Bag-hash seed; 0 = default |
| Method | Purpose |
|---|---|
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_cDisjoint 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 Field | Default | Purpose |
|---|---|---|
ui32Arms | 0 | [0 or 2, 8]; < 2 leaves bandit inert |
ui32Features | 0 | [1, 16] |
decAlpha | 0.30 | Optimism weight on posterior std |
decRidge | 1.0 | A prior diagonal; larger = slower learning |
| Method | Purpose |
|---|---|
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_cOnline 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.
| Method | Purpose |
|---|---|
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_cSplit/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.
| Method | Purpose |
|---|---|
init(alpha, minResiduals) | Configure miscoverage |
pushResidual(bucket, absResidual) | Feed residual |
admits(bucket, yHat, sigma, horizon, cost, theta) | Admission decision struct |
changePoint_cBayesian online change-point detection (BOCPD). Run-length posterior over Normal predictive model with constant hazard. Truncated at 600 run lengths. Fixed double[600] arrays.
| Method | Purpose |
|---|---|
init(hazardLambda, knownSigma, shortRunThreshold) | Configure |
update(observation) | Returns break probability struct |
valueHead_cRecursive least squares with ridge regularization and exponential forgetting. Up to 32 features. Fixed double[32] + double[32×32].
| Method | Purpose |
|---|---|
init(dim, delta, gamma, ridge) | Configure |
predict(features) | Linear prediction |
update(features, target) | One RLS step |
tailIndex_cExtreme-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.
| Method | Purpose |
|---|---|
push(absReturn) | Ingest one absolute log-return |
compute() | Hill, ES99, fragility struct |
algoPromotionPolicy_cThe 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 Field | Default | Purpose |
|---|---|---|
ui32WindowSize | 256 | Rolling window length in labels (clamped to 512) |
ui32MinLabels | 32 | Labels required before leaving COLD |
ui32MinAgreeLabels | 16 | Agreeing labels required to compare |
decMinAgreeFrac | 0.5 | Agreement-rate floor for meaningful comparison |
decMinEdgeGainBps | 0 | Challenger gain over incumbent required to promote |
decDemoteEdgeBps | 0 | Serving floor; below it the layer is demoted |
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_cThe 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 Field | Default | Purpose |
|---|---|---|
eModel | LOGISTIC | LOGISTIC or MLP |
ui32Folds | 5 | K-fold count [1,32] |
ui32Gap | 2 | Samples purged before each test block |
eCalibration | PLATT_CONFORMAL | none / platt / conformal / platt_conformal |
decConformalAlpha | 0.1 | Coverage target (90% intervals) |
ui64Seed | golden ratio | Splitmix64 seed; same corpus + config → byte-identical bundle |
| Method | Purpose |
|---|---|
configure(config_s) | Select model, split, calibration, seed |
train(corpus, outBundle, outReport) | Fit model, calibrate, emit versioned bundle |
algoWeightBundle_cPlain 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.
| Method | Purpose |
|---|---|
predict(features, count) | Probability and conformal interval |
contentHash() | Stable FNV-1a fingerprint over model payload |
toJson() / fromJson() | Append-only state-file section |
| Field | Notes |
|---|---|
standardizer.mean[F], standardizer.scale[F] | Input normalization; scale 0 = constant |
logistic.weights[F], logistic.intercept | Linear head on standardized inputs |
mlp.w1[H*F] (row-major), mlp.b1[H], mlp.w2[H], mlp.b2 | Tanh 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 |
.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.
All regime detectors implement algoRegimeDetector_c and produce algoRegimeResult_s
with regime classification, signal quality, trend/volatility state, strength, confidence, and validity flag.
algoRegimeTypes.h)| Type | Kind | Values |
|---|---|---|
algoMarketRegime_e | enum | UNKNOWN, TRENDING_UP, TRENDING_DOWN, RANGE_BOUND, HIGH_VOLATILITY, LOW_VOLATILITY, BREAKOUT, MEAN_REVERTING |
algoSignalQuality_e | enum | NONE, WEAK, MODERATE, STRONG, VERY_STRONG |
algoTrendState_e | enum | FLAT, UPTREND, DOWNTREND, TRANSITIONING |
algoVolatilityState_e | enum | NORMAL, COMPRESSED, EXPANDING, ELEVATED |
algoRegimeResult_s | struct | eRegime, eQuality, eTrend, eVolatility, decStrength, decConfidence, fValid |
algoRegimeHmm_cWraps 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.
| Config | Default | Purpose |
|---|---|---|
i32StateCount | 3 | HMM states [2,4] |
decStayProbability | 0.95 | Transition diagonal |
decEwmaAlpha | 0.02 | Online learning rate |
decTrendThreshold | 0.6 | Posterior ≥ this → trending |
decRangeThreshold | 0.4 | Posterior < this → transitioning |
algoRegimeAdx_cClassic 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.
| Config | Default |
|---|---|
ui32Period | 14 (max 256) |
decTrendingThreshold | 25 |
decStrongTrendThreshold | 40 |
decRangeThreshold | 20 |
algoRegimeBollinger_cBollinger bandwidth and %B. Detects squeeze (low bandwidth → breakout imminent) and expansion (high bandwidth → elevated vol). Input: close prices.
| Config | Default |
|---|---|
ui32Period | 20 (max 512) |
decBandWidth | 2 |
decSqueezeThreshold | 0.005 |
decExpansionThreshold | 0.03 |
algoRegimeVolCluster_cShort-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.
| Config | Default |
|---|---|
ui32ShortWindow | 10 |
ui32LongWindow | 100 (max 512) |
decExpansionRatio | 1.5 |
decCompressionRatio | 0.7 |
algoRegimeCvd_cRolling 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.
| Config | Default | Purpose |
|---|---|---|
ui32Window | 50 (max 512) | Rolling correlation window |
decAccumulationThreshold | 0.3 | Corr > this → TRENDING_UP |
decDistributionThreshold | -0.3 | Corr < this → TRENDING_DOWN |
decDivergenceThreshold | 0.5 | |corr| < this with large CVD → MEAN_REVERTING |
All strength calculators implement algoRegimeStrength_c and produce a normalized
decimal_t strength [0,1] plus an algoSignalQuality_e mapping.
algoCompositeStrength_cCombines up to 8 weighted source strengths into a single composite. Clamped to [0,1]. Quality mapped through configurable thresholds.
| Config | Default | Purpose |
|---|---|---|
ui32SourceCount | 0 (max 8) | Number of sources |
arrWeights | {} | Per-source weight |
decStrongThreshold | 0.7 | → STRONG |
decModerateThreshold | 0.4 | → MODERATE |
decWeakThreshold | 0.2 | → WEAK |
| Method | Purpose |
|---|---|
setSource(index, value) | Set one source strength |
compute() | Calculate weighted composite |
strength() | Last computed composite |
quality() | Threshold-mapped quality |
algoTrendConviction_cFast/slow EMA spread in bps plus consecutive-bar persistence tracking. Strength blends normalized absolute spread and consecutive-bar count. Spread below minimum yields zero.
| Config | Default |
|---|---|
ui32EmaFastPeriod | 5 |
ui32EmaSlowPeriod | 20 |
ui32ConsecutiveBars | 3 |
decMinSpreadBps | 5 |
Outputs: strength() [0,1], quality(), trendState() (FLAT/UPTREND/DOWNTREND/TRANSITIONING), emaSpread() raw bps.
algoVolNormalization_cCurrent vol as ratio of Welford running mean. Drives both strength output and discrete volatility state classification (NORMAL/COMPRESSED/EXPANDING/ELEVATED).
| Config | Default |
|---|---|
ui32Lookback | 100 |
decLowVolThreshold | 0.5 (≤ → COMPRESSED) |
decHighVolThreshold | 1.5 (≥ → EXPANDING) |
decExtremeVolThreshold | 2.5 (≥ → ELEVATED) |
algoFlowImbalance_cBuy/sell imbalance as signed-flow / total-flow over a trailing window via algoSignedFlowBuckets_c. Feed from onMarketdataTick, read in onMarketdataOhlcClose.
| Config | Default |
|---|---|
ui32BucketCount | 60 |
ui64BucketDurationMs | 1000 |
ui64WindowMs | 30000 |
decStrongThreshold | 0.6 |
decModerateThreshold | 0.3 |
On-demand candle analytics and signed-flow accumulation. Not indicator plugins — stateless pure functions and bucket rings with zero per-bar cost when unused.
On-demand pure functions over the candle ring. Zero per-bar cost when unused. Header-only.
| Function | Purpose |
|---|---|
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_cRing 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.
| Method | Purpose |
|---|---|
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 |
Multi-asset covariance, lead/lag transmission, Mahalanobis turbulence, and synchronous BBO resampling for cross-venue strategies.
algoCrossAssetEngine_cEWMA 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.
| Method | Purpose |
|---|---|
init(assetCount, ewmaAlpha) | Configure |
update(returns, count) | Ingest return vector |
compute() | Recompute eigenfactor |
laggingScore(asset) | (factor × loading − return) / sigma |
dominantShare() | λ[0] / Σλ |
algoXCorrLeadLag_cRolling 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.
| Method | Purpose |
|---|---|
init(window, maxLag) | Configure |
update(leadReturn, lagReturn) | Push paired observation |
bestLag() | Winning lag index |
score() | max(rho) × sign(lead at best lag) |
algoTurbulence_cMahalanobis turbulence index via EWMA mean/covariance + eigendecomposition. Static variance-ratio helper. Fixed decimal_t[8][8] arrays.
| Method | Purpose |
|---|---|
init(dim, ewmaAlpha) | Configure |
update(values, count) | Ingest observation vector |
turbulence() | Mahalanobis distance |
volRatio(shortVar, longVar) | Static; ≥ 1 means expansion |
algoVenueGrid_cSynchronous 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].
| Method | Purpose |
|---|---|
init(venueCount, gridMs) | Configure |
update(venue, quote) | Ingest BBO sample |
snapshot(now, maxStaleMs, out) | Write quotes; returns fresh count |
Low-level mathematical building blocks: eigensolver, rough-path signatures, and optimal transport displacement profiles.
algoEig_cFixed-capacity symmetric Jacobi eigensolver (up to 8×8). Solver internals in double; API boundary in decimal_t. Caller-provided output arrays.
| Method | Purpose |
|---|---|
solve(matrix, dim, outEigenvalues, outEigenvectors) | A = V·diag(λ)·Vᵀ |
dominantShare(eigenvalues, dim) | λ[0] / Σλ |
reconstruct(eigenvalues, eigenvectors, dim, out) | Rebuild A |
reconstructionError(...) | Accuracy metric |
pathSignature_cTruncated path log-signature (rough-path theory). Chen recursion levels 1–3 on up to 3 channels, projected onto 14 Lyndon words. Accumulation in double.
| Method | Purpose |
|---|---|
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_cQuantile-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.
| Method | Purpose |
|---|---|
compute(prevBook, curBook, tick) | Full displacement profile struct |