Skip to main content

mts1b-quantkit — public API surface

Allocators

from mts1b_quantkit.allocators import (
hrp_weights, black_litterman, markowitz, ledoit_wolf,
risk_parity, risk_parity_long_short,
)


# HRP — López de Prado 2016
result = hrp_weights(returns_df)
# HRPResult(weights=pd.Series, linkage=np.ndarray, leaves=list, leaf_order=list)


# Black-Litterman with views
bl = black_litterman(
returns_df,
market_caps={"AAPL": 3e12, "MSFT": 2.8e12, ...},
views=[{"symbols": ["AAPL"], "weights": [1.0], "expected": 0.12, "confidence": 0.6}],
risk_aversion=2.5,
tau=0.05,
view_uncertainty_factor=1.0,
)
weights = bl["weights"] # dict[symbol, weight]


# Markowitz mean-variance
weights = markowitz(returns_df, risk_aversion=2.0, constraints={...})


# Ledoit-Wolf shrinkage (for input to other allocators)
cov_shrunk = ledoit_wolf(returns_df)


# Equal Risk Contribution (no shorts)
weights = risk_parity(returns_df, max_iter=1000)


# L/S variant
weights = risk_parity_long_short(returns_df,
long_universe=[...], short_universe=[...])

Cross-validation

from mts1b_quantkit.cv import walk_forward, purged_kfold, combinatorial_cv

# Walk-forward
cv = walk_forward(
factor=get("f_my_factor"),
params_grid={"h": [10, 21, 42]},
universe="us-large-cap",
start="2014-01-01", end="2024-01-01",
train_window=252, test_window=63, step=63,
rebal="monthly",
sizing={"method": "equal_weight_ls", "n_long": 10, "n_short": 10},
cost_bps=10,
)
print(cv["agg_sharpe"], cv["best_params"], cv["stability_score"])

# Purged CV (handles lookback overlap)
cv = purged_kfold(factor=..., n_folds=10, purge_window=21, embargo=5, ...)

# Combinatorial CV (exhaustive)
cv = combinatorial_cv(factor=..., n_train_folds=8, n_test_folds=2, ...)

Metrics

from mts1b_quantkit.metrics import (
sharpe, sharpe_from_moments, calmar, max_drawdown,
cagr, omega, sortino, ulcer_index,
)
import numpy as np

returns = np.array([0.01, -0.005, 0.008, ...])

sharpe(returns, periods_per_year=252) # 1.43
calmar(returns) # 0.92
max_drawdown(returns) # -0.12 (12% DD)
cagr(returns) # 0.18 (18% CAGR)
omega(returns, threshold=0.0) # 1.65
sortino(returns, periods_per_year=252) # 1.88

# Numerically-stable Sharpe from precomputed moments (CUDA-friendly)
import cupy as cp
sum_r = cp.array([...]) # (N,)
sum_r2 = cp.array([...])
n = 252
sharpe_arr = sharpe_from_moments(sum_r, sum_r2, n_obs=n, periods_per_year=252)

Statistics

from mts1b_quantkit.stats import (
information_coefficient, bootstrap_sharpe_ci, decay_curve,
t_stat_from_returns, autocorrelation,
)

ic = information_coefficient(factor_values=z_scores, future_returns=ret_1d)
# ~0.05 typical

ci = bootstrap_sharpe_ci(returns, n_boot=1000, alpha=0.05)
print(ci.lower, ci.upper) # [0.82, 1.43]

ic_curve = decay_curve(factor=get("f_my_factor"), params={"h": 21},
horizons=[1, 5, 10, 21, 42, 63], universe="us-large-cap")
# dict[horizon, ic]

t = t_stat_from_returns(returns, periods_per_year=252)
ar1 = autocorrelation(returns, lag=1)

Options Greeks

from mts1b_quantkit.options import bs_greeks, black_scholes, implied_vol

# Greeks
g = bs_greeks(spot=100, strike=105, t=30/365, r=0.05, vol=0.30, q=0.0, option="call")
# Greeks(price=2.45, delta=0.412, gamma=0.045, theta=-0.018, vega=0.123, rho=0.034)

# Just the price
price = black_scholes(spot=100, strike=105, t=30/365, r=0.05, vol=0.30, option="put")

# Implied vol (Brent solver)
iv = implied_vol(market_price=2.55, spot=100, strike=105, t=30/365, r=0.05, option="call")

Risk metrics

from mts1b_quantkit.risk_metrics import (
var_historical, var_parametric, expected_shortfall, cvar,
)

var95 = var_historical(returns, alpha=0.05) # -0.034 (i.e., 3.4% loss)
var95_p = var_parametric(returns, alpha=0.05) # parametric Gaussian
es95 = expected_shortfall(returns, alpha=0.05) # avg loss beyond VaR
cv = cvar(returns, alpha=0.05) # alias for ES

Cost models

from mts1b_quantkit.cost_models import (
compute_fee, compute_slippage, venue_cost_model,
)

cost = venue_cost_model(
venue="coinbase",
symbol=Symbol("BTC-USD"),
side="buy",
quantity=Decimal("0.5"),
price=Decimal("95000"),
is_taker=True,
)
# CostBreakdown(fee=23.75, spread=2.5, slippage=15.0, total=41.25)

fee = compute_fee(venue="ibkr", asset_class="equities",
notional_usd=Decimal("10000"))
slip = compute_slippage(symbol=..., quantity=..., adv_usd=...)

Universe filters

from mts1b_quantkit.universe_filters import (
passes_adv_filter, passes_market_cap, passes_price_filter,
)

mask = passes_adv_filter(
universe=["AAPL", "MSFT", "TINY_CORP"],
adv_threshold_usd=10_000_000,
lookback_days=21,
)
# [True, True, False]

mask = passes_market_cap(universe=..., min_cap_usd=1e9, max_cap_usd=1e12)
mask = passes_price_filter(universe=..., min_price=5.0, max_price=1000.0)

Regime classifiers

from mts1b_quantkit.regime import (
classify_regime, vix_regime, trend_regime, volatility_regime,
)

regime = classify_regime(asof=date(2026, 5, 23))
# {"vix": "normal", "trend": "bull", "breadth": "narrow", "composite": "bull"}

vix_regime(asof=date(2026, 5, 23)) # "low" | "normal" | "high" | "crisis"
trend_regime("SPY", asof=date.today()) # "bull" | "chop" | "bear"
volatility_regime(returns, lookback=21) # similar enum

Factor primitives

from mts1b_quantkit.factors import (
register, get, FACTOR_REGISTRY,
zscore_cross_sectional, winsorize, ewma_std, rolling_corr,
)

# Register a factor
@register("f_my_momentum")
def f_my_momentum(panel, h=21):
return zscore_cross_sectional(panel.close[-1] / panel.close[-h] - 1)

# Discover
print(sorted(FACTOR_REGISTRY))
fn = get("f_my_momentum")

# Primitives
z = zscore_cross_sectional(values) # winsorize at ±3σ then standardize
w = winsorize(values, lower=0.01, upper=0.99)
sigma = ewma_std(returns, alpha=0.94, window=21)
corr = rolling_corr(a, b, window=63)

CPU vs GPU

Most functions accept xp:

import numpy as np
import cupy as cp

# CPU
hrp_weights(returns_pd, xp=np)

# GPU (10-100x faster for large universes)
returns_cp = cp.asarray(returns_pd.values)
hrp_weights(returns_cp, xp=cp)

xp is auto-detected from input type when omitted.

See also