API Reference: Regime Classification¶
Classify market regimes for conditional performance analysis.
Functions¶
classify_volatility_regime¶
Classify volatility regime using rolling window.
def classify_volatility_regime(
values: np.ndarray,
window: int = 13,
basis: Literal["changes", "levels"] = "changes",
low_percentile: float = 33.0,
high_percentile: float = 67.0,
) -> np.ndarray
Parameters:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
|
required |
Time series values |
|
|
|
Rolling window (13 weeks ≈ 1 quarter) |
|
|
|
|
|
|
|
LOW volatility threshold |
|
|
|
HIGH volatility threshold |
Returns: Array of regime labels ("LOW", "MED", "HIGH")
CRITICAL: Use basis="changes" (default). Using "levels" mislabels steady drifts as volatile.
Example:
from temporalcv.regimes import classify_volatility_regime
# Classify volatility on changes (correct)
vol_regimes = classify_volatility_regime(prices, window=13, basis="changes")
print(np.unique(vol_regimes, return_counts=True))
classify_direction_regime¶
Classify direction using thresholded signs.
def classify_direction_regime(
values: np.ndarray,
threshold: float,
) -> np.ndarray
Parameters:
Parameter |
Type |
Description |
|---|---|---|
|
|
Values to classify (changes) |
|
|
Move threshold |
Returns: Array of direction labels ("UP", "DOWN", "FLAT")
Classification:
|value| > thresholdandvalue > 0→"UP"|value| > thresholdandvalue < 0→"DOWN"|value| <= threshold→"FLAT"
get_combined_regimes¶
Combine volatility and direction into single label.
def get_combined_regimes(
vol_regimes: np.ndarray,
dir_regimes: np.ndarray,
) -> np.ndarray
Parameters:
Parameter |
Type |
Description |
|---|---|---|
|
|
Volatility labels |
|
|
Direction labels |
Returns: Combined labels like "HIGH-UP", "LOW-FLAT", etc.
Example:
from temporalcv.regimes import (
classify_volatility_regime,
classify_direction_regime,
get_combined_regimes,
)
from temporalcv import compute_move_threshold
# Classify
vol = classify_volatility_regime(prices, basis="changes")
threshold = compute_move_threshold(train_actuals)
direction = classify_direction_regime(actuals, threshold)
# Combine
combined = get_combined_regimes(vol[-len(actuals):], direction)
print(np.unique(combined, return_counts=True))
get_regime_counts¶
Get sample counts per regime.
def get_regime_counts(regimes: np.ndarray) -> Dict[str, int]
Parameters:
Parameter |
Type |
Description |
|---|---|---|
|
|
Regime labels |
Returns: Dict of counts, sorted by count descending
mask_low_n_regimes¶
Mask regime labels with insufficient samples.
def mask_low_n_regimes(
regimes: np.ndarray,
min_n: int = 10,
mask_value: str = "MASKED",
) -> np.ndarray
Parameters:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
|
required |
Regime labels |
|
|
|
Minimum samples required |
|
|
|
Value for masked regimes |
Returns: Regimes with low-n cells masked
Example:
from temporalcv.regimes import mask_low_n_regimes
# Mask unreliable regimes
masked = mask_low_n_regimes(combined, min_n=10)
# Only evaluate on reliable regimes
for regime in np.unique(masked):
if regime == "MASKED":
continue
mask = masked == regime
mae = np.mean(np.abs(preds[mask] - actuals[mask]))
print(f"{regime}: MAE = {mae:.4f} (n={mask.sum()})")
Best Practices¶
Use changes basis: Always use
basis="changes"for volatilityCheck sample counts: Use
mask_low_n_regimesbefore interpretingTraining-only thresholds: Compute direction threshold from training data
Align arrays: Ensure volatility and direction arrays have same length