Skip to main content

Discrete-time stochastic processes, Monte Carlo, analytics, and reporting.

Project description

stochlab

stochlab logo

A compact library for discrete-time stochastic processes, Monte Carlo simulation, and analytics.


📦 Installation

stochlab is published as a standard Python package and targets Python 3.11+.

pip install stochlab

Optional extras:

  • pip install "stochlab[docs]" – build the Sphinx documentation locally.
  • pip install "stochlab[dev]" – formatting, linting, typing, and test tooling.

Verify your install:

>>> from stochlab import MarkovChain, analytics
>>> import numpy as np
>>> P = np.array([[0.7, 0.3], [0.4, 0.6]])
>>> mc = MarkovChain.from_transition_matrix(["Bull", "Bear"], P)
>>> analytics.stationary_distribution(mc).distribution
array([0.57142857, 0.42857143])

🚀 What is stochlab?

stochlab is a Python library for finite / countable discrete-time stochastic processes.

It's designed to be:

  • Coherence – built around clear Mathematical objects:
    • a finite state space $S = {s_0, s_1, \ldots, s_{n-1}}$,
    • a discrete-time process $(X_t)_{t=0}^T$ with values in $S$,
    • sample paths and Monte Carlo experiments.
  • OOP - Models/Processes are defined as objects inheriting from the parent class StochasticProcess
  • Engineer-friendly – clean abstractions, type hints, tests, and a modular layout ready to grow.
  • Practical – aims at use cases like:
    • Markov chains (credit ratings, user journeys, regimes),
    • simple queueing models,
    • branching processes (viral growth, extinction),
    • Monte Carlo estimation + variance reduction,
    • DataFrame summaries and interactive plots (later phases).

Right now the project is in early stages: Phase 1 focuses on solid core abstractions with the first concrete model (MarkovChain) implemented and tested.


🚀 Quick Start

Installation

# Clone the repository
git clone https://github.com/oscarthse/stochlab.git
cd stochlab

# Install with uv (recommended)
uv sync

# Or install in development mode
uv pip install -e .

Basic Usage

import numpy as np
from stochlab.core import StateSpace
from stochlab.models import MarkovChain

# Define a simple 2-state Markov chain
states = ["Bull", "Bear"]
P = np.array([[0.7, 0.3],   # Bull -> Bull: 70%, Bull -> Bear: 30%
              [0.4, 0.6]])  # Bear -> Bull: 40%, Bear -> Bear: 60%

# Create the Markov chain
mc = MarkovChain.from_transition_matrix(states, P)

# Simulate a single path
path = mc.sample_path(T=100, x0="Bull")
print(f"Path length: {len(path)}")
print(f"Final state: {path[-1]}")

# Run Monte Carlo simulation
result = mc.simulate_paths(n_paths=1000, T=100)
df = result.to_dataframe()
print(f"Simulated {len(result)} paths")

# Analyze state distribution at time T=50
dist = result.state_distribution(t=50)
print(f"State distribution at t=50: {dist}")

Mathematical Foundation

The library implements discrete-time stochastic processes with mathematical precision:

State Space

Every process operates on a finite state space:

S = \{s_0, s_1, \ldots, s_{n-1}\}

States can be any hashable Python objects: strings, numbers, tuples, or custom types. The StateSpace class provides a clean mapping between labels (like "A", "BBB", (regime,vol)) and integer indices $0, 1, \ldots, n-1$.

Stochastic Process

A discrete-time stochastic process is a sequence of random variables:

(X_t)_{t=0}^T, \quad X_t \in S

Each model implements the sample_path() method to generate realizations of length $T+1$.

Sample Paths

A sample path represents one possible evolution of the process:

\omega = (X_0(\omega), X_1(\omega), \ldots, X_T(\omega))

Represented by a Path object holding arrays of times and states, with optional metadata in the extras dictionary.

Monte Carlo Simulation

Generate multiple independent paths to estimate:

  • State probabilities: $P(X_t = s)$
  • Path functionals: $E[f(X_0, \ldots, X_T)]$
  • Hitting times, absorption probabilities, etc.

The SimulationResult class collects multiple paths and provides analysis methods like DataFrame conversion and empirical state distributions.


🧮 Analytical Solutions (Finite Markov Chains)

The stochlab.analytics module packages classical finite-state Markov chain formulas with validation and friendly outputs. Every routine accepts either a raw numpy.ndarray transition matrix or a MarkovChain instance (preserving state labels).

Stationary Distributions

Find $\pi$ satisfying

\pi P = \pi, \qquad \sum_{i=0}^{n-1} \pi_i = 1.

We solve

\begin{bmatrix}
P^{\top} - I \\
\mathbf{1}^{\top}
\end{bmatrix} \pi =
\begin{bmatrix}
0 \\
1
\end{bmatrix}

via least squares, clip tiny negatives, renormalize, and report $|\pi P - \pi|_1$ so you can judge accuracy. Irreducible aperiodic chains yield a unique solution; reducible chains may have multiple stationary distributions, and the solver returns one valid vector.

from stochlab.analytics import stationary_distribution

res = stationary_distribution(mc)
print(res.distribution)
print(res.residual)
print(res.states)

Expected Hitting Times

For a target set $T$, the hitting time $\tau_T = \inf{t \ge 0 : X_t \in T}$ has expectation

h = (I - Q)^{-1} \mathbf{1},

where $Q$ restricts $P$ to non-target states. Targets themselves have $h_i = 0$. If $(I - Q)$ is singular (targets unreachable) the implementation raises a clear RuntimeError.

from stochlab.analytics import hitting_times
res = hitting_times(mc, targets=["Bear"])
print(res.times)
print(res.target_mask)

Absorption Probabilities & Times

Partition states into transient $T$ and absorbing $A$ so that

P = \begin{bmatrix}
Q & R \\
0 & I
\end{bmatrix}.

The fundamental matrix $N = (I - Q)^{-1}$ yields

  • $B = N R$: probability of ending in each absorbing state.
  • $t = N \mathbf{1}$: expected steps before absorption.
from stochlab.analytics import absorption_probabilities

res = absorption_probabilities(
    mc.P,
    transient_states=["Active", "Dormant"],
    absorbing_states=["Churned"],
    state_space=mc.state_space,
)
print(res.probabilities)
print(res.expected_steps)

Rows supplied as absorbing are validated to ensure they are truly absorbing (identity rows), preventing silent misuse.


🏗️ Architecture

stochlab follows a layered architecture designed for extensibility and mathematical rigor:

Core Layer (stochlab.core)

Fundamental building blocks that all models depend on:

  • StateSpace: Manages finite state sets with bijective label ↔ index mapping
  • Path: Represents a single trajectory $(X_0, X_1, \ldots, X_T)$ with validation and immutability
  • StochasticProcess: Abstract base class defining the interface all models must implement
  • SimulationResult: Collection of paths with analysis methods (DataFrame conversion, empirical distributions)

Models Layer (stochlab.models)

Concrete implementations of stochastic processes:

  • MarkovChain: Finite-state, time-homogeneous Markov chains with validation and convenience constructors
  • RandomWalk: Reflecting random walk on bounded integers
  • MM1Queue: Capped M/M/1 queue with exponential event clocks and overflow detection
  • Coming soon: GaltonWatsonProcess, birth–death processes

Analytics Layer (stochlab.analytics)

Finite-state analytical routines:

  • stationary_distribution, hitting_times, absorption_probabilities
  • Dataclass outputs with state labels, residual diagnostics, and model-safe validation

Future Layers

  • stochlab.mc: Advanced Monte Carlo engines with variance reduction
  • stochlab.reporting: Visualization and reporting tools

🛠️ Development

Development Setup

# Install development dependencies
make dev

# Run tests
make test

# Code quality checks
make format    # Format with black
make lint      # Lint with ruff
make typecheck # Type check with mypy
make all-checks # Run all quality checks

Project Structure

stochlab/
├── src/stochlab/           # Main package
│   ├── core/              # Core abstractions
│   ├── models/            # Concrete models
│   └── __init__.py
├── tests/                 # Test suite
├── Makefile              # Development automation
├── pyproject.toml        # Project configuration
└── README.md

Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/new-model
  3. Implement your changes following the architecture
  4. Add tests for new functionality
  5. Run make all-checks to ensure quality
  6. Submit a pull request

🎯 Roadmap

Phase 1: Core Foundation ✅

  • StateSpace, Path, SimulationResult classes
  • StochasticProcess abstract interface
  • MarkovChain implementation with comprehensive validation
  • Comprehensive test suite (19 tests passing)
  • Development workflow (Makefile, linting, formatting)

Phase 2: Model Expansion

  • RandomWalk - symmetric and asymmetric random walks
  • MM1Queue - single-server queueing model
  • GaltonWatsonProcess - branching processes
  • Birth-death processes

Phase 3: Advanced Monte Carlo

  • MonteCarloEngine with variance reduction
  • Antithetic variates, control variates
  • Parallel simulation support
  • Rare event simulation techniques

Phase 4: Analytics & Theory

  • Markov chain analytics (stationary distributions, hitting times, absorption)
  • Queueing metrics (L, W, Lq, Wq)
  • Branching process extinction probabilities
  • Spectral analysis tools

Phase 5: Visualization & Reporting

  • Interactive plots with Plotly
  • Jupyter notebook integration
  • Statistical summaries and reports
  • Export to common formats (CSV, JSON, HDF5)

📚 Examples & Use Cases

Financial Modeling

# Credit rating transitions
ratings = ["AAA", "AA", "A", "BBB", "BB", "B", "CCC", "D"]
P = credit_transition_matrix()  # Your transition matrix
mc = MarkovChain.from_transition_matrix(ratings, P)

# Simulate rating paths
result = mc.simulate_paths(n_paths=10000, T=60)  # 5 years monthly
default_prob = result.state_distribution(t=60)["D"]

Market Regime Modeling

# Bull/Bear market transitions
states = ["Bull", "Bear", "Sideways"]
P = np.array([[0.85, 0.10, 0.05],
              [0.15, 0.70, 0.15],
              [0.20, 0.20, 0.60]])

mc = MarkovChain.from_transition_matrix(states, P)
result = mc.simulate_paths(n_paths=1000, T=252)  # 1 year daily

# Analyze regime persistence
df = result.to_dataframe()
regime_changes = df.groupby('path_id')['state'].apply(lambda x: (x != x.shift()).sum())

Epidemiological Modeling

# Simple SIR-like model (future implementation)
states = ["Susceptible", "Infected", "Recovered"]
# Custom transition probabilities based on infection/recovery rates

Operations Research

# Queue length analysis (future MM1Queue implementation)
queue = MM1Queue(arrival_rate=0.8, service_rate=1.0)
result = queue.simulate_paths(n_paths=1000, T=1000)
# Analyze steady-state queue length distribution

🔬 Technical Features

Robust Validation

  • Transition matrices: Validates stochastic properties (rows sum to 1, non-negative)
  • State spaces: Ensures uniqueness and proper label-index mapping
  • Paths: Enforces time-state array consistency and immutability
  • Initial distributions: Validates probability distribution properties

Performance Optimizations

  • Efficient numpy arrays: Core simulation uses vectorized operations
  • Memory optimization: slots=True on dataclasses reduces memory footprint
  • Immutable trajectories: Read-only arrays prevent accidental modification

Type Safety

  • Modern Python typing: Full type hints with Python 3.11+ syntax
  • Abstract interfaces: Clear contracts between components
  • Runtime validation: Comprehensive error checking with informative messages

📄 License

MIT License - see LICENSE file for details.


🤝 Acknowledgments

Built with modern Python tools:

  • uv for dependency management
  • pytest for testing
  • black for code formatting
  • ruff for linting
  • mypy for type checking
  • numpy for numerical computing
  • pandas for data analysis

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

stochlab-0.1.0.tar.gz (27.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

stochlab-0.1.0-py3-none-any.whl (22.2 kB view details)

Uploaded Python 3

File details

Details for the file stochlab-0.1.0.tar.gz.

File metadata

  • Download URL: stochlab-0.1.0.tar.gz
  • Upload date:
  • Size: 27.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.8

File hashes

Hashes for stochlab-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d4f0374fc369afbef3f8a9040bca16fb7342c390bd7bc652fb945bf697085223
MD5 235d88835b7e2df07cce5fc2972ebafb
BLAKE2b-256 431df596739c83a29612126ea625e6a3ef9a92c5d27b6add27fb69c80f0fcc55

See more details on using hashes here.

File details

Details for the file stochlab-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: stochlab-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 22.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.8

File hashes

Hashes for stochlab-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b8377565775a6b225c3b4560cc4d3f55a6fc244c30639ce77860598061e9438c
MD5 e6bb2b6cc6ef56876b045e20061de1b8
BLAKE2b-256 16c9d07246b88a2a291108c8447e4f57f380f86c8226a8a6fdeb03003cdf4962

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page