mts1b-research — public API surface
Strategy discovery + ladder sweep + factor library + live executor + drift monitor.
Factor registry
from mts1b_research.factors import register, get, FACTOR_REGISTRY
@register("f_my_momentum")
def f_my_momentum(panel, /, h: int = 21):
return zscore_cross_sectional(panel.close[-1] / panel.close[-h] - 1)
# Discover
print(sorted(FACTOR_REGISTRY))
fn = get("f_my_momentum")
Strategy registry
from mts1b_research.strategies import StrategyRegistry, StrategySpec
await StrategyRegistry.register(
StrategySpec(
strategy_id="momentum_v3",
factor="f_momentum_12_1",
params={"h_long": 252, "h_skip": 21},
universe="us-large-cap",
rebal="monthly",
sizing="kelly_voltarget_12",
cost_bps=5,
enabled=True,
)
)
# Query
active = await StrategyRegistry.active()
spec = await StrategyRegistry.get("momentum_v3")
# Lifecycle
await StrategyRegistry.disable("momentum_v3")
await StrategyRegistry.halve_allocation("momentum_v3", reason="early decay")
await StrategyRegistry.shadow("momentum_v3", reason="drift > -2.0σ")
Ladder sweep
from mts1b_research.ladder import run_ladder
await run_ladder(
factor_class="momentum",
param_grid={
"h_long": list(range(60, 365, 5)),
"h_skip": [0, 5, 21, 42],
"winsorize": [True, False],
},
universe="us-large-cap",
start="2010-01-01", end="2024-01-01",
cost_bps=5,
# Stage configs (defaults shown)
l1_keep_pct=0.01,
l2_min_stability=0.5,
l3_regimes=["bull", "chop", "crash"],
l4_cost_multiplier=2.0,
l5_max_candidates=5,
)
Writes survivors per stage to data/sweeps/ladder/<run_id>/.
Live executor
from mts1b_research.strategies import live_executor
# Long-running worker
await live_executor.run(
fund_id="paper-momentum",
strategies_from="registry", # or explicit list
)
What it does:
- At each rebalance window, looks up active strategies
- Computes factor on latest
UniversePanel - Applies sizer in
mts1b-portfolio - Diffs against current OMS positions
- Emits child orders via OMS
CLI: mts1b-research live-executor run --fund-id paper-momentum.
Dual-paper
from mts1b_research.strategies import DualPaperExecutor
executor = DualPaperExecutor(
strategy_id="momentum_v3",
paper_fund="paper-momentum-demo",
live_fund="live-momentum",
diff_threshold_bps=10.0,
)
await executor.run()
Runs the SAME strategy code against both books; alerts on divergence > threshold.
Drift monitor
from mts1b_research.ops import drift_monitor
# Polled (Prefect-scheduled)
result = await drift_monitor.measure(strategy_id="momentum_v3")
# DriftMeasurement(
# strategy_id="momentum_v3",
# backtest_ic=0.062, backtest_sharpe=1.43,
# live_ic_30d=0.054, live_sharpe_30d=1.27,
# drift_zscore=-0.24,
# decay_status="NORMAL", # or "WARN" | "HALVE" | "SHADOW"
# )
# Manual
await drift_monitor.evaluate_all() # checks all active strategies
Auto-throttle thresholds:
drift_zscore | Action |
|---|---|
< -0.5σ | Telegram warning |
< -1.0σ | Halve sleeve allocation |
< -2.0σ | Shadow the strategy |
Factory ensembles
from mts1b_research.factory import canonical_alpha_factory, factory_ensemble
# Discover N candidate factors
candidates = await canonical_alpha_factory.discover(
asset_class="equities",
target_count=50,
min_walkforward_sharpe=0.5,
min_ic=0.02,
min_stability=0.5,
)
# Compose into a meta-strategy
ensemble = factory_ensemble(
candidates=candidates,
method="hrp", # or "equal" | "min_var"
)
# Returns a registered meta-strategy id
NATS subjects
| Subject | Direction | Payload |
|---|---|---|
mts.v1.research.signals.published | publish | Signal |
mts.v1.research.ladder.stage_complete | publish | stage summary dict |
mts.v1.research.drift.measured | publish | drift snapshot dict |
mts.v1.marketdata.bars.* | subscribe | latest bars for rebal |
mts.v1.oms.fills.created | subscribe | observe live execution |
CLI
mts mts1b-research factors list
mts mts1b-research strategy register --strategy-id X --factor Y --params '...'
mts mts1b-research strategy show --strategy-id X
mts mts1b-research strategies list --enabled-only
mts mts1b-research ladder run --factor-class momentum --param-grid '...'
mts mts1b-research drift show --strategy-id X
mts mts1b-research live-executor run --fund-id Y --strategies-from registry