Metadata-Version: 2.4
Name: timesmith
Version: 0.1.2
Summary: TimeSmith for ML models
Author-email: "Kyle T. Jones" <kyletjones@gmail.com>
Maintainer-email: "Kyle T. Jones" <kyletjones@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/kylejones200/timesmith
Project-URL: Documentation, https://timesmith.readthedocs.io/
Project-URL: Repository, https://github.com/kylejones200/timesmith
Project-URL: Bug Tracker, https://github.com/kylejones200/timesmith/issues
Project-URL: Changelog, https://github.com/kylejones200/timesmith/blob/main/CHANGELOG.md
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pandas<3.0.0,>=1.5.0
Requires-Dist: numpy<3.0.0,>=1.20.0
Provides-Extra: forecasters
Requires-Dist: pmdarima<3.0.0,>=2.0.0; extra == "forecasters"
Requires-Dist: statsmodels<1.0.0,>=0.14.0; extra == "forecasters"
Requires-Dist: prophet<2.0.0,>=1.1.0; extra == "forecasters"
Provides-Extra: deep-learning
Requires-Dist: darts<1.0.0,>=0.28.0; extra == "deep-learning"
Provides-Extra: kalman
Requires-Dist: filterpy<2.0.0,>=1.4.5; extra == "kalman"
Provides-Extra: network
Requires-Dist: networkx<4.0.0,>=3.0; extra == "network"
Requires-Dist: numba<1.0.0,>=0.57.0; extra == "network"
Provides-Extra: scipy
Requires-Dist: scipy<2.0.0,>=1.10.0; extra == "scipy"
Provides-Extra: distances
Requires-Dist: tslearn<1.0.0,>=0.6.0; extra == "distances"
Provides-Extra: changepoint
Requires-Dist: ruptures<2.0.0,>=1.1.0; extra == "changepoint"
Provides-Extra: bayesian
Requires-Dist: pymc<6.0.0,>=5.0.0; extra == "bayesian"
Requires-Dist: arviz<1.0.0,>=0.15.0; extra == "bayesian"
Provides-Extra: ensemble
Requires-Dist: scikit-learn<2.0.0,>=1.0.0; extra == "ensemble"
Provides-Extra: performance
Requires-Dist: joblib<2.0.0,>=1.0.0; extra == "performance"
Provides-Extra: wavelet
Requires-Dist: PyWavelets<2.0.0,>=1.4.0; extra == "wavelet"
Provides-Extra: data-loaders
Requires-Dist: pandas-datareader<1.0.0,>=0.10.0; extra == "data-loaders"
Requires-Dist: yfinance<1.0.0,>=0.2.0; extra == "data-loaders"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: black>=23.0; extra == "dev"
Requires-Dist: flake8>=6.0; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Provides-Extra: docs
Requires-Dist: sphinx>=7.0; extra == "docs"
Requires-Dist: sphinx-rtd-theme>=2.0; extra == "docs"
Requires-Dist: sphinx-autodoc-typehints>=1.20; extra == "docs"
Provides-Extra: examples
Requires-Dist: jupyter>=1.0; extra == "examples"
Requires-Dist: notebook>=7.0; extra == "examples"
Requires-Dist: ipykernel>=6.0; extra == "examples"
Requires-Dist: plotsmith>=0.1.0; extra == "examples"
Provides-Extra: anomsmith
Requires-Dist: anomsmith>=0.1.0; extra == "anomsmith"
Provides-Extra: all
Requires-Dist: pmdarima>=2.0.0; extra == "all"
Requires-Dist: statsmodels>=0.14.0; extra == "all"
Requires-Dist: networkx>=3.0; extra == "all"
Requires-Dist: tslearn>=0.6.0; extra == "all"
Requires-Dist: ruptures>=1.1.0; extra == "all"
Requires-Dist: pymc>=5.0.0; extra == "all"
Requires-Dist: arviz>=0.15.0; extra == "all"
Requires-Dist: scikit-learn>=1.0.0; extra == "all"
Requires-Dist: PyWavelets>=1.4.0; extra == "all"
Requires-Dist: prophet>=1.1.0; extra == "all"
Requires-Dist: darts>=0.28.0; extra == "all"
Requires-Dist: filterpy>=1.4.5; extra == "all"
Requires-Dist: pandas-datareader>=0.10.0; extra == "all"
Requires-Dist: yfinance>=0.2.0; extra == "all"
Requires-Dist: joblib>=1.0.0; extra == "all"
Requires-Dist: plotsmith>=0.1.0; extra == "all"
Requires-Dist: anomsmith>=0.1.0; extra == "all"
Requires-Dist: pytest>=7.0; extra == "all"
Requires-Dist: pytest-cov>=4.0; extra == "all"
Requires-Dist: black>=23.0; extra == "all"
Requires-Dist: flake8>=6.0; extra == "all"
Requires-Dist: mypy>=1.0; extra == "all"
Requires-Dist: ruff>=0.1.0; extra == "all"
Requires-Dist: sphinx>=7.0; extra == "all"
Requires-Dist: sphinx-rtd-theme>=2.0; extra == "all"
Requires-Dist: sphinx-autodoc-typehints>=1.20; extra == "all"
Requires-Dist: jupyter>=1.0; extra == "all"
Requires-Dist: notebook>=7.0; extra == "all"
Requires-Dist: ipykernel>=6.0; extra == "all"
Dynamic: license-file

# TimeSmith

[![PyPI version](https://badge.fury.io/py/timesmith.svg)](https://badge.fury.io/py/timesmith)
[![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Tests](https://github.com/kylejones200/timesmith/workflows/Tests/badge.svg)](https://github.com/kylejones200/timesmith/actions)
[![Documentation](https://readthedocs.org/projects/timesmith/badge/?version=latest)](https://timesmith.readthedocs.io/)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)

TimeSmith is a time series machine learning library with strict layer boundaries and a clean architecture.

## Architecture

TimeSmith uses a four-layer architecture with strict boundaries:

### Layer 1: Typing (`timesmith/typing`)
Scientific types and runtime validators for time series data structures:
- `SeriesLike`: pandas Series or single-column DataFrame with datetime/int index
- `PanelLike`: DataFrame with entity key plus time index
- `TableLike`: DataFrame with row index aligned to time
- `ForecastLike`: Forecast results with predictions and optional intervals

### Layer 2: Core (`timesmith/core`)
Base classes, parameter handling, tags, and input validation:
- `BaseObject`: Parameter management (`get_params`, `set_params`, `clone`)
- `BaseEstimator`: Base class with `fit` capability
- `BaseTransformer`: Transformers with `transform` and optional `inverse_transform`
- `BaseForecaster`: Forecasters with `predict` and optional `predict_interval`
- `BaseDetector`: Anomaly detectors with `score` and `predict`
- `BaseFeaturizer`: Transformers that output `TableLike` data

### Layer 3: Compose (`timesmith/compose`)
Pipeline and adapter objects for composition:
- `Pipeline`: Chains transformer steps with scitype change support
- `ForecasterPipeline`: Transformer(s) then forecaster
- `Adapter`: Converts between scitypes (Series ↔ Table)
- `FeatureUnion`: Runs multiple featurizers and concatenates results

### Layer 4: Tasks & Eval (`timesmith/tasks`, `timesmith/eval`)
Task objects and evaluation tools:
- `ForecastTask`: Binds data, horizon, and target semantics
- `DetectTask`: Anomaly detection task definition
- `ExpandingWindowSplit`, `SlidingWindowSplit`: Cross-validation splitters
- `backtest_forecaster`: Run backtests with metrics
- `summarize_backtest`: Aggregate and per-fold metrics

## Quick Example

```python
import pandas as pd
from timesmith import ForecastTask, backtest_forecaster, make_forecaster_pipeline
from timesmith.examples import NaiveForecaster, LogTransformer

# Load data
y = pd.Series([...], index=pd.date_range("2020-01-01", periods=100))

# Create forecast task
task = ForecastTask(y=y, fh=5, frequency="D")

# Build pipeline
transformer = LogTransformer(offset=1.0)
forecaster = NaiveForecaster()
pipeline = make_forecaster_pipeline(transformer, forecaster=forecaster)

# Run backtest
result = backtest_forecaster(pipeline, task)

# Summarize results
summary = summarize_backtest(result)
print(f"Mean MAE: {summary['aggregate_metrics']['mean_mae']:.4f}")
```

## Running the Example

```bash
python examples/basic_forecast.py
```

This will:
1. Load/generate example data
2. Create a forecast task
3. Build a pipeline with transformer and forecaster
4. Run backtest
5. Print summary metrics

## Installation

```bash
pip install timesmith
```

## Development

```bash
# Install in development mode
pip install -e ".[dev]"

# Run tests
pytest tests/

# Format code
black timesmith tests

# Run linting
flake8 timesmith tests
```

## Features

- **Model Serialization**: Save and load fitted models
- **Comprehensive Error Handling**: Custom exceptions with context
- **Logging Configuration**: Centralized logging with environment variable support
- **Data Validation**: Edge case handling and data quality checks
- **Pipeline Composition**: Flexible transformer and forecaster pipelines
- **Backtesting**: Time series cross-validation with multiple metrics
- **Network Analysis**: Graph-based time series analysis
- **Multiple Forecasters**: ARIMA, Prophet, LSTM, Bayesian, and more

## Model Serialization

```python
from timesmith import SimpleMovingAverageForecaster, save_model, load_model

# Fit and save
forecaster = SimpleMovingAverageForecaster(window=5)
forecaster.fit(y)
save_model(forecaster, "model.pkl")

# Load later
loaded = load_model("model.pkl")
forecast = loaded.predict(fh=10)
```

## Error Handling

TimeSmith provides custom exceptions for better error handling:

```python
from timesmith import NotFittedError, DataError, ValidationError

try:
    forecaster.predict(fh=5)
except NotFittedError as e:
    print(f"Error: {e}")
    print(f"Context: {e.context}")
```

## Logging

Configure logging via environment variables:

```bash
export TIMESMITH_LOG_LEVEL=DEBUG
export TIMESMITH_LOG_FORMAT=detailed
```

Or programmatically:

```python
from timesmith.logging_config import configure_logging
configure_logging(level="INFO")
```

## Design Principles

1. **Strict Layer Boundaries**: Core cannot import eval. Typing cannot import anything.
2. **Validation at Boundaries**: Validate once at public API boundaries only.
3. **Task Semantics**: Tasks hold semantics. Estimators only store params and fitted state.
4. **Composition**: Use pipelines and adapters for flexible workflows.
5. **Type Safety**: Scientific types with runtime validators for data structures.

## Requirements

**Core dependencies (minimal):**
- Python 3.12 or higher
- pandas >= 1.5.0
- numpy >= 1.20.0

**Optional dependencies:**
- `scipy` - For filters, changepoint detection, distances (install: `pip install timesmith[scipy]`)
- `networkx` - For network analysis features (install: `pip install timesmith[network]`)
- See `pyproject.toml` for all optional dependency groups
- networkx >= 3.0

See `pyproject.toml` for optional dependencies for specific forecasters.
