Metadata-Version: 2.4
Name: quant-ml-toolkit
Version: 0.2.0
Summary: Building blocks for quantitative ML pipelines: technical features, preprocessing, feature selection, splitting and random-forest training.
Author: leoniedong
License-Expression: MIT
Project-URL: Homepage, https://github.com/leoniedong/quant-ml-toolkit
Project-URL: Repository, https://github.com/leoniedong/quant-ml-toolkit
Keywords: quant,finance,machine-learning,technical-analysis,feature-engineering
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Operating System :: OS Independent
Classifier: Topic :: Office/Business :: Financial :: Investment
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pandas>=2.2.3
Requires-Dist: numpy>=1.26
Requires-Dist: scipy>=1.11
Requires-Dist: scikit-learn>=1.3
Requires-Dist: python-dateutil>=2.8
Requires-Dist: matplotlib>=3.7
Provides-Extra: shap
Requires-Dist: shap>=0.44; extra == "shap"
Provides-Extra: talib
Requires-Dist: TA-Lib>=0.4.28; extra == "talib"
Provides-Extra: all
Requires-Dist: shap>=0.44; extra == "all"
Requires-Dist: TA-Lib>=0.4.28; extra == "all"
Provides-Extra: test
Requires-Dist: pytest>=7.0; extra == "test"
Dynamic: license-file

# quant-ml-toolkit

[![PyPI version](https://img.shields.io/pypi/v/quant-ml-toolkit)](https://pypi.org/project/quant-ml-toolkit/)
[![Python versions](https://img.shields.io/pypi/pyversions/quant-ml-toolkit)](https://pypi.org/project/quant-ml-toolkit/)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

A small Python toolkit for building quantitative machine-learning pipelines —
from raw OHLCV price data through to a trained, explainable model.

The pieces are designed to chain together, but each is usable on its own:

```
raw OHLCV
   -> technical features        (TechnicalFeatureCalculator)
   -> cleaning & scaling        (FeaturePreprocessor)
   -> feature selection         (FeatureSelector)
   -> train / val / test split  (SampleSplit)
   -> model training + SHAP     (RandomForestModelTrainer)
```

## Installation

```bash
pip install quant-ml-toolkit
```

The base install is lightweight. Two features need optional extras:

```bash
pip install "quant-ml-toolkit[talib]"   # technical features (needs the TA-Lib C library, see below)
pip install "quant-ml-toolkit[shap]"    # SHAP explanations
pip install "quant-ml-toolkit[all]"     # everything
```

`TechnicalFeatureCalculator` depends on [TA-Lib](https://github.com/TA-Lib/ta-lib-python),
whose Python wrapper requires the underlying TA-Lib **C library** to be installed
separately (e.g. `brew install ta-lib`, `conda install -c conda-forge ta-lib`, or
your platform's package manager).

**Requires Python 3.10–3.13.**

## Quick start

The examples assume price data pulled from Yahoo Finance via
[`yfinance`](https://github.com/ranaroussi/yfinance).

> **Note on yfinance columns.** Recent versions of `yfinance` return a
> *MultiIndex* column layout by default (e.g. `('Close', 'AAPL')`).
> `TechnicalFeatureCalculator` matches columns by the suffixes
> `Open`/`High`/`Low`/`Close`/`Volume`, so pass `multi_level_index=False`
> to get the flat columns it expects:

```python
import yfinance as yf

ohlcv = yf.download(
    "AAPL", start="2018-01-01", end="2023-12-31",
    multi_level_index=False,   # -> flat Open/High/Low/Close/Volume columns
)
```

### 1. Compute technical features

```python
from quant_ml_toolkit import TechnicalFeatureCalculator

calc = TechnicalFeatureCalculator(ohlcv)
features = calc.get_feature_df(
    technical_indicators_close=True,   # Return, ROC, RSI, volatility, Bollinger bands, ...
    technical_indicators_ohlc=True,    # ATR, CCI, Stochastic, ADX, Aroon, Williams %R, ...
    level_measures=True,               # SMA/EMA (10/20/50/200)
    volume_change=True,                # volume % change
    lag_close=True, lag_return=True,   # lagged close / return columns
)
```

You can also pass a single close-price **Series** instead of a DataFrame; in that
case only the close-based indicators are computed.

### 2. Build a target and split

```python
import numpy as np
from quant_ml_toolkit import SampleSplit

# example target: sign of next-day return (a simple up/down classification)
features["target"] = np.sign(ohlcv["Close"].pct_change().shift(-1))
data = features.dropna()

feature_cols = [c for c in data.columns if c != "target"]

# chronological split (shuffle=False by default — important for time series)
X_train, y_train, X_test, y_test = SampleSplit.TrainTestXYSplit(
    data, feature_variables=feature_cols, target_variables=["target"],
    train_size=80, test_size=20,
)
```

### 3. Preprocess (fit on train, apply to test)

```python
from quant_ml_toolkit import FeaturePreprocessor

pp = FeaturePreprocessor(X_train, test_features_df=X_test)
pp.handle_missing_values()
pp.handle_infinity_values()
pp.handle_outlier_values_boundary_method(z_threshold=3)
pp.normalize(standardize=True)
X_train, X_test = pp.load_data()
```

All statistics (fill values, outlier bounds, the scaler) are fitted on the
training set only and then applied to the test set, so there is no look-ahead
leakage.

### 4. Select features

```python
from quant_ml_toolkit import FeatureSelector

fs = FeatureSelector(X_train, X_test, y_train.squeeze(), model_type="Classification")
fs.remove_constant_features()
fs.remove_correlated_features(corr_thld=0.9)
fs.select_feature_by_mutual_information(select_k=20)
X_train, X_test = fs.X_train, fs.X_test
```

### 5. Train, tune and explain

```python
from quant_ml_toolkit import RandomForestModelTrainer

trainer = RandomForestModelTrainer(
    X_train, X_test, y_train.squeeze(), y_test.squeeze(),
    model_type="classification",
)

# randomized hyperparameter search over a sensible default grid
trainer.fit(random_search=True, scoring="accuracy", n_iter=25, cv=3)

predictions = trainer.predict()

# feature importance via SHAP (requires the [shap] extra)
trainer.compute_shap_values()
importance = trainer.get_shap_values_df()      # mean |SHAP| per feature, sorted
trainer.shap_summary_plot(title="Feature importance").show()
```

## Modules

| Module | Key API | What it does |
|---|---|---|
| `data` | `to_period_timestamp`, `rolling_window`, `monthly_return_from_daily_close` | Date parsing, walk-forward in/out-of-sample windows, daily→monthly returns |
| `features` | `TechnicalFeatureCalculator` | Technical-indicator feature engineering (TA-Lib) |
| `preprocessing` | `FeaturePreprocessor`, `get_dummy_and_numerical_variables` | Leakage-safe missing/inf/outlier handling and scaling |
| `selection` | `FeatureSelector` | Constant/correlation/mutual-information/RFE/ROC-AUC selection |
| `splitting` | `SampleSplit` | Percentage-based train/val/test and X/y splits |
| `modelling` | `RandomForestModelTrainer` | Random-forest training, randomized search, SHAP |

## License

MIT
