🔥 pathforge
Simulate realistic financial markets from historical price data — for strategy testing, research, and risk analysis.
Why pathforge?
Testing a trading strategy on a single historical price series tells you how it performed on one specific path the market happened to take. That's not enough. A robust strategy should work across the full range of outcomes the market could have produced.
pathforge learns the statistical behaviour of any asset from its historical prices and generates hundreds of realistic alternative price paths. Test your strategy across all of them and you'll know how robust it really is.
Installation
pip install pathforge
pip install numba # required for markov_egarch model
To use the built-in plot functionality:
pip install pathforge[examples]
Quick Start
import pathforge as pf
import yfinance as yf
# Download historical price data
ticker = yf.Ticker("AAPL")
prices = ticker.history(period="5y")["Close"]
# Create a forge and fit a model
forge = pf.PathForge(prices)
forge.fit(model="garch")
# Simulate one year of trading days across 100 paths
sim = forge.simulate(days=252, n_paths=100, seed=42)
# Explore the results
sim.summary()
sim.plot()
# Get the paths as a DataFrame for your own analysis
df = sim.to_dataframe() # shape: (253, 100)
Models
| Model | model= |
Best for |
|---|---|---|
| Markov-switching EGARCH | "markov_egarch" |
Research-grade: hidden regimes + volatility clustering + fat tails |
| Geometric Brownian Motion | "gbm" |
Fast baseline, simple assumptions |
| GARCH(1,1) | "garch" |
Realistic volatility clustering |
| Block Bootstrap | "bootstrap" |
Non-parametric, no distributional assumptions |
| Merton Jump Diffusion | "jump_diffusion" |
Capturing sudden crashes and spikes |
Which model should I use?
- GBM — good sanity check, fast, but underestimates tail risk
- GARCH — best for most use cases, captures the volatility clustering seen in real markets
- Bootstrap — most honest for strategy testing, resamples real historical behaviour directly
- Jump Diffusion — best when your data contains sudden large moves you want to preserve
- Markov-switching EGARCH — the most sophisticated model. Identifies hidden market regimes (calm, stressed, crisis) each with its own EGARCH volatility dynamics and Student-t innovations. Captures regime persistence, volatility clustering, leverage effects, and fat tails simultaneously. Requires minimum 2 years of daily data and Numba for speed optimisation.
Usage Notes
Markov-switching EGARCH
The markov_egarch model has specific requirements and options:
- Minimum data: 2 years of daily prices (500+ observations recommended)
- Fitting time: ~1 minute on a modern machine (first call longer due to Numba JIT warmup)
- Dependencies: requires
numba—pip install numba
forge = pf.PathForge(prices)
forge.fit(
model="markov_egarch",
n_states=3, # number of hidden regimes
n_starts=3, # random restarts for EM algorithm
verbose=True, # print fitting progress
random_state=42, # for reproducibility
min_persistence=0.7 # minimum regime persistence (set to None to disable)
)
sim = forge.simulate(days=252, n_paths=100)
Note: This model uses a generalised EM algorithm rather than an exact closed-form M-step. Volatility dynamics are modelled using state-specific, uncentred EGARCH filters, resulting in an approximate likelihood. This approach is designed for practical simulation and backtesting rather than exact state-space inference. See the GitHub repository for full technical details.
API Reference
PathForge(data)
The main class. Pass a pd.Series or pd.DataFrame of daily closing prices.
| Method | Description |
|---|---|
.fit(model="garch") |
Fit a simulation model to the historical data |
.simulate(days=252, n_paths=100, start_price=None, seed=None) |
Generate simulated price paths |
SimulationResult
Returned by .simulate().
| Attribute / Method | Description |
|---|---|
.paths |
np.ndarray of shape (days+1, n_paths) |
.to_dataframe() |
Paths as a pd.DataFrame, one column per path |
.summary() |
Print statistical summary of the simulation |
.plot(max_paths=50) |
Plot simulated paths with historical context |
Roadmap
- Merton Jump Diffusion
- Markov-switching EGARCH with Student-t innovations
- Intraday timeframes (1m, 5m, 15m, 1h)
- Multi-asset correlated simulation
- Centred EGARCH specification
- CLI:
pathforge simulate AAPL --days 252 --paths 500
Contributing
PRs and issues welcome at github.com/franmanz/pathforge.
License
MIT © 2026 franmanz
Metadata
Release files for pathforge 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pathforge-0.2.1.tar.gz | 15.6 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pathforge-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.2 kB
Release files / pathforge-0.2.1.tar.gz
| Download URL | pathforge-0.2.1.tar.gz |
|---|---|
| Size | 15.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7046b63e8baa347d45dbb5bd250ec7eab484817b7d6a8ebf5b2bf07f3ba51122
|
|
BLAKE2b-256 checksum How to use checksums |
1481ffb886321e845e8273805d2482b581904d0481092e4370f59336fe5a755f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|
Release files / pathforge-0.2.1-py3-none-any.whl
| Download URL | pathforge-0.2.1-py3-none-any.whl |
|---|---|
| Size | 15.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1927851ecce82f988165b4b4b84600bc39ee7e0910550e8595a299d94b0e41ab
|
|
BLAKE2b-256 checksum How to use checksums |
33e69ee2d9d0e42dedb1a6b19acbe5bde9ed25e4fbc9ff4f4d518a4434419115
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|
Security for pathforge 0.2.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.