Skip to main content

mts1b-portfolio — public API surface

Sizers, session matrix, capacity, holding buckets, multi-sleeve composition.

Sizers

from mts1b_portfolio.sizers import (
equal_weight_long, equal_weight_ls, kelly_fraction,
vol_target_weights, kelly_voltarget_12, fixed_weight,
)

# Equal-weight top-N long-only
weights = equal_weight_long(signal=z_scores, n=10, gross=1.0)

# Equal-weight L/S
weights = equal_weight_ls(signal=z_scores, n_long=5, n_short=5, gross=1.0)

# Kelly fraction (Markowitz with cap)
w = kelly_fraction(
expected_returns=mu, # (A,)
cov=sigma, # (A, A)
risk_aversion=2.0,
cap=0.20, # max 20% any single position
)

# Vol target overlay
w_scaled = vol_target_weights(
base_weights=w,
asset_log_returns=hist_lr, # (T, A)
target_ann_vol=0.12,
window=63,
max_scale=3.0,
)

# Composite — kelly + voltarget@12% (the default for v1 demo)
w_final = kelly_voltarget_12(
signal=z_scores,
returns=hist_returns,
nav_usd=Decimal("100000"),
)

# Fixed-weight (override for static portfolios)
w = fixed_weight({"SPY": 0.6, "TLT": 0.3, "GLD": 0.1})

Session matrix

from mts1b_portfolio.session import SessionMatrix
from datetime import datetime, timezone

matrix = SessionMatrix({
"RTH": {"sizer": "kelly_voltarget_12", "gross_cap": 1.0},
"pre": {"sizer": "kelly_voltarget_8", "gross_cap": 0.3},
"post": {"sizer": "kelly_voltarget_8", "gross_cap": 0.3},
"IBEOS": {"sizer": "equal_weight_ls", "gross_cap": 0.1},
"24h": {"sizer": "kelly_voltarget_12", "gross_cap": 1.0},
})

sizer = matrix.resolve(asset_class="equities", asof=datetime.now(timezone.utc))
weights = sizer(signal=z_scores, n_long=5, n_short=5)

Capacity

from mts1b_portfolio.capacity import position_capacity, fund_capacity
from decimal import Decimal

# Per-position cap from ADV
cap = position_capacity(
symbol="AAPL",
nav_usd=Decimal("100000"),
fraction_of_adv=0.01, # at most 1% of 21-day ADV
adv_lookback_days=21,
)
# Decimal('5234.50')


# Per-fund cap on dollar growth (capacity ceiling)
ceiling = fund_capacity(
fund_id="paper-momentum",
strategy_id="momentum_v3",
target_sharpe=1.5,
)
# Decimal('2500000') — the fund can grow to $2.5M before capacity-degraded

Holding buckets

from mts1b_portfolio.holding import bucket, attribute_pl

# Classify holding period
b = bucket("intraday") # exit within session
b = bucket("daily") # < 5 days
b = bucket("weekly") # 5-21 days
b = bucket("monthly") # 21-63 days
b = bucket("quarterly") # 63-252 days


# Attribute realized P/L by holding bucket
attribution = attribute_pl(
fund_id="paper-momentum",
start=date(2026, 1, 1),
end=date(2026, 5, 23),
)
# {"intraday": Decimal("...$"), "daily": ..., "weekly": ..., ...}

Multi-sleeve composition

from mts1b_portfolio.multi_sleeve import compose, compose_with_hrp

# Static allocations
composite = compose(
sleeves={
"momentum": {"weights": {"AAPL": 0.5, "MSFT": 0.5}, "allocation": 0.5},
"carry": {"weights": {"TLT": 1.0}, "allocation": 0.3},
"value": {"weights": {"VTV": 1.0}, "allocation": 0.2},
},
overlay="equal", # weighted sum
)
# {"AAPL": 0.25, "MSFT": 0.25, "TLT": 0.30, "VTV": 0.20}


# Dynamic allocation via HRP on sleeve returns
composite = compose_with_hrp(
sleeves={
"momentum": {"weights": {...}, "returns_history": ...},
"carry": {"weights": {...}, "returns_history": ...},
"value": {"weights": {...}, "returns_history": ...},
},
lookback_days=252,
)

See also