Skip to content

Latest commit

 

History

History
177 lines (125 loc) · 5.5 KB

File metadata and controls

177 lines (125 loc) · 5.5 KB

Interface contracts

Purpose: New/updated interface contracts with function signatures, error handling, and determinism guarantees.
Canonical spec: ../master_architecture_spec.md


These contracts are designed to fit your current architecture: small, typed, deterministic functions; SQLite remains the store of record; artifacts remain hash-addressed and logged.


Component: Residualizer

Inputs

  • returns_df (wide: index=ts_utc, cols=asset_id + factor cols)
  • factor_cols: list[str]
  • mode: "rolling_ols" | "kalman"
  • window_bars, min_obs
  • as_of_lag_bars (enforces causality; default = 1 for "trade next bar")

Outputs

  • FactorOutputs: {betas_dict, alpha_df, r2_df, residual_df, metadata}

Function signatures (pseudocode)

interface Residualizer:
  compute(
    returns_df: DataFrame,
    factor_cols: list[str],
    config: FactorModelConfig,
    as_of_lag_bars: int = 1
  ) -> FactorOutputs

Error handling

  • Raise ValueError if factor_cols missing entirely or index not monotonic.
  • Return empty frames if insufficient data per asset (consistent with current "graceful degradation" patterns).

Determinism guarantees

  • Sort index ascending; sort columns lexicographically.
  • No global RNG use; if Kalman uses randomness (it shouldn't), require an explicit seed and log it.

Leakage hardening requirement

  • Must enforce as_of_lag_bars: residual at time t used for signal at t must be computed using returns ≤ t−as_of_lag_bars. (This fixes the current "full sample OLS" leakage risk in signal_residual_momentum_24h.)

Example

  • compute(returns_df, ["BTC_spot","ETH_spot"], config, as_of_lag_bars=1) → FactorOutputs with residual_df aligned to returns index.

Component: RegimeDetector

Inputs

  • market_series (e.g., BTC returns, dispersion, vol proxy)
  • fit_window (train-only window)
  • inference_mode: "filter" (no smoothing in test)

Outputs

  • regime_states: series or DataFrame with ts_utc, label, prob

Function signatures

interface RegimeDetector:
  fit(train_data: DataFrame, config: RegimeConfig) -> RegimeModel
  predict(test_data: DataFrame, mode: str = "filter") -> RegimeStateSeries

Error handling

  • Raise if asked to run mode="smooth" in test or if train/test windows overlap.

Determinism guarantees

  • Fixed optimizer seeds (if any), stable ordering, and strict separation of fit() and predict().

Required invariants

  • fit() uses only train_data; predict(mode="filter") uses no future data in test. mode="smooth" in test must raise.

Example

  • fit(train_df, config) → model; predict(test_df, mode="filter") → RegimeStateSeries with ts_utc, label, prob.

Component: ExecutionCostModel

This unifies today's cost logic in portfolio.apply_costs_to_portfolio() and the per-asset liquidity slippage proxy in cli/backtest.py.

Inputs

  • weights_df (target portfolio)
  • prev_weights_df or implicit lag
  • bars_meta (liquidity, volume proxies)
  • model_params (fee_bps, spread_bps_model, impact_model, max_participation)

Outputs

  • net_returns time series
  • cost_breakdown per period: fee, spread, impact

Function signatures

interface ExecutionCostModel:
  apply_costs(
    gross_returns: Series,
    weights: DataFrame,
    market_meta: DataFrame,
    config: ExecutionConfig
  ) -> tuple[Series, CostFrame]

Error handling

  • If required meta missing: either raise (strict mode) or fall back to conservative defaults (explicitly logged).

Determinism guarantees

  • No randomness; if scheduling simulation uses pseudo-random fills, require a seed and persist it.

Required invariants

  • Same (gross_returns, turnover, config) → same net_returns and cost_breakdown. Missing liquidity → conservative default (e.g. 50 bps) when configured.

Example

  • apply_costs(gross_returns, turnover_series, fee_bps=30, slippage_bps=10) → (net_returns, cost_breakdown).

Component: MultipleTestingAdjuster

Inputs

  • table of hypotheses with p-values (e.g., per signal × horizon × parameter)
  • dependency mode ("bh" or "by")

Outputs

  • adjusted p-values + "discoveries" boolean flags

Function signatures

interface MultipleTestingAdjuster:
  adjust(p_values: Series, method: str, q: float) -> AdjustedPValues

Determinism guarantees

  • Same p_values and (method, q) → same adjusted p-values and discovery set. No RNG.

Note

  • Romano–Wolf: implemented, opt-in via CRYPTO_ANALYZER_ENABLE_ROMANOWOLF=1; outputs rw_adjusted_p_values in RC summary when enabled. See Methods & Limits and implementation_ledger.

Example

  • adjust(p_values, method="bh", q=0.05) → adjusted p-values and discoveries boolean flags.

Component: Bootstrapper

Inputs

  • return series
  • method: block_fixed | stationary
  • seed
  • block_length rules

Outputs

  • resampled statistic distribution + CI

Function signatures

interface Bootstrapper:
  sample(series: Series, config: BootstrapConfig) -> ndarray
  ci(samples: ndarray, ci_pct: float) -> tuple[float, float]

Error handling

  • Invalid config (e.g. block_length < 1) → raise or return empty; small series → informative message.

Determinism guarantees

  • Fixed seed in config → identical sample indices and CI for same series and config. Seed must be stored in artifacts.

Example

  • sample(returns_series, BootstrapConfig(method="stationary", seed=42)) → ndarray of resampled statistic; ci(samples, 0.95) → (lo, hi).