Back to profiles
Quant Researcher

ArXiv β†’ Live Backtest
in Minutes

Regime-switching HMM, Rust Differential Evolution, CARA portfolio optimisation β€” full reproducible research stack. Jupyter-native. DuckDB-native. Rust-native.

πŸ¦€ Optimiz-R (Rust DE) 🐍 Jupyter / Polarway 🧠 HMM Β· MCMC Β· CARA πŸ—„οΈ DuckDB Lakehouse
Request Early Access
Research Pipeline

From raw market data to a deployed strategy β€” one Docker stack

1 β€” Data Ingestion (Polarway)
Yahoo Finance / CCXT feeds β†’ Polars DataFrame β†’ Parquet lake. Point-in-time joins via DuckDB prevent lookahead bias.
2 β€” Regime Detection (HMM Β· Rust Baum-Welch)
Gaussian HMM with k=3 states fitted to daily log-returns. Rust Baum-Welch converges in <2ms / 500 obs. Viterbi state sequence decoded in <0.5ms.
3 β€” Parameter Estimation (MCMC Β· Rust)
Metropolis-Hastings posterior over regime-conditional means and covariances. 10,000 MCMC samples in <800ms via mcmc_sample Rust binding.
4 β€” Portfolio Optimisation (CARA Β· Optimiz-R DE)
CARA utility maximisation per regime. For non-convex parameter spaces, Differential Evolution (Optimiz-R) finds the global optimum without gradient information.
5 β€” Backtesting (Rust backtest engine)
522-day full backtest with transaction costs (10 bps), slippage model, and rebalancing schedule β€” all in a single backtest_with_costs_rust call.
6 β€” Reporting (DuckDB + Streamlit)
Results written to DuckDB leaderboard with time-travel support. Streamlit dashboard renders interactive P&L, regime attribution, and weight charts.
Hidden Markov Model β€” Regime Detection

Identify Bull / Bear / Sideways regimes in real time with Rust Baum-Welch

The model has hidden states $Q = \{q_1,\ldots,q_K\}$ (market regimes) emitting observable log-returns $O = \{r_1,\ldots,r_T\}$ drawn from regime-conditional Gaussians:

Emission probability
$$P(r_t \mid q_t = k) = \mathcal{N}\!\left(r_t;\;\mu_k,\;\sigma_k^2\right)$$
Forward variable (E-step)
$$\alpha_t(k) = P(r_1,\ldots,r_t,\,q_t=k\mid\lambda)$$ $$\alpha_t(k) = \left[\sum_j \alpha_{t-1}(j)\,a_{jk}\right] b_k(r_t)$$

The Viterbi algorithm recovers the most likely hidden path:

Viterbi recursion
$$\delta_t(k) = \max_{q_{1:t-1}}\,P(q_1,\ldots,q_{t-1},q_t=k,r_{1:t}\mid\lambda)$$

Live fit on SPY/QQQ/IWM/EEM/EFA/GLD/TLT/VNQ (Jan 2024 – Mar 2026):

Detected Regime Sequence β€” 8-ETF Basket
Jan 24 Jul 24 Jan 25 Jan 26 Bull 31% Sideways 44% Bear 26%

Regime-conditional daily returns (annualised): Bull +29% Sideways +8% Bear -12%

CARA Optimisation + Differential Evolution

Global optimizer for non-convex utility landscapes β€” Rust-native DE from Optimiz-R

The CARA (Constant Absolute Risk Aversion) utility yields closed-form weights for a Gaussian regime:

CARA optimal weights (unconstrained)
$$w^* = \frac{1}{\gamma}\,\Sigma_k^{-1}\,\mu_k$$

For constrained problems β€” long-only, leverage cap, or non-Gaussian regimes β€” HFThot uses Differential Evolution from the optimiz-r crate. The DE mutation operator:

DE mutation
$$\mathbf{v}_i = \mathbf{x}_{r_1} + F\,(\mathbf{x}_{r_2} - \mathbf{x}_{r_3}), \quad F\in[0,2]$$
DE crossover + selection
$$u_{i,j} = \begin{cases} v_{i,j} & \text{if } U[0,1] < CR \\ x_{i,j} & \text{otherwise} \end{cases}$$ $$\mathbf{x}_i^{t+1} = \begin{cases} \mathbf{u}_i & \text{if } f(\mathbf{u}_i) \leq f(\mathbf{x}_i^t) \\ \mathbf{x}_i^t & \text{otherwise} \end{cases}$$
# advanced_portfolio_optimization.ipynb β€” HMM + CARA
import hft_lab_core as hft

# ── 1. Fit HMM (Rust Baum-Welch, 3 regimes) ──
hmm_params = hft.fit_hmm(returns.values, n_states=3)
state_seq  = hft.viterbi_decode(returns.values, hmm_params)

# ── 2. Regime-conditional ΞΌ / Ξ£ ──────────────
regime_portfolios = {}
for k in range(3):
    mask  = (state_seq == k)
    mu_k  = returns[mask].mean().values * 252   # annualised
    cov_k = returns[mask].cov().values * 252

    # ── CARA closed-form ──────────────────────
    gamma = {"Bear": 5.0, "Sideways": 2.0, "Bull": 1.0}[regime_names[k]]
    w = hft.cara_optimal_weights_rust(mu_k, cov_k, gamma=gamma)

    # ── DE for constrained optimisation ───────
    from optimizr import DifferentialEvolution
    de = DifferentialEvolution(pop_size=60, F=0.8, CR=0.9, max_iter=200)
    w_constrained = de.optimize(
        objective=lambda w: -sharpe(mu_k, cov_k, w),
        bounds=[(βˆ’0.3, 1.0)] * len(mu_k),
        constraint=lambda w: np.sum(w) == 1.0
    )
    regime_portfolios[regime_names[k]] = w_constrained
Strategy Leaderboard

522-day backtest Β· 8 ETFs Β· 10 bps transaction cost Β· Rust engine

3.34
Multi-Strategy CARA SR
2.54
Momentum SR
1.40
Adaptive HMM SR
βˆ’4.7%
Adaptive Max DD
<2ms
Rust backtest (522d)
Leaderboard β€” Cumulative Returns by Strategy (Jan 2024 – Mar 2026)
+50% +35% +20% +10% 0% Jan 24 Jul 24 Jan 25 Jul 25 Mar 26 Multi-Strategy CARA SR=3.34 Momentum SR=2.54 Adaptive HMM SR=1.40 B&H SR=1.78

⚑ Rust Performance (vs pure Python)

150Γ—
HMM Baum-Welch
200Γ—
CARA weight solve
80Γ—
Full backtest loop
Research Stack

Every component is open-source or in the HFThot toolkit

πŸ¦€
hfthot-lab-core
Rust crate β€” HMM, CARA, backtest, MCMC, cointegration, signature features
βš™οΈ
optimiz-r
Rust Differential Evolution with PyO3 bindings β€” global portfolio optimisation
πŸ»β€β„οΈ
Polarway
Polars-native ETL pipeline β€” Parquet lake, DuckDB queries, no Pandas overhead
πŸ““
Jupyter Notebooks
Reproducible research β€” kernel: rhftlab (Python 3.11 + all deps)
πŸ—„οΈ
DuckDB Lakehouse
Strategy leaderboard with time-travel β€” no lookahead in point-in-time analytics
🐳
Docker Stack
Single docker-compose up β€” Jupyter + Streamlit + DuckDB + Rust ready
References