Metadata-Version: 2.4
Name: friction-engine
Version: 0.1.0
Summary: Realistic backtest friction modeling: volume-aware slippage, multi-market fees & taxes (US/TW/JP), liquidity constraints, and MAE/MFE trade analytics.
Author: friction-engine contributors
License: Apache-2.0
Project-URL: Homepage, https://github.com/jalano0i9u8y7-lab/friction-engine
Keywords: backtest,slippage,transaction-costs,MAE,MFE,trading
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial :: Investment
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Dynamic: license-file

# friction-engine

**Your backtest is lying to you — this library measures how much.**

`friction-engine` models the four costs naive backtests ignore, as small,
composable, fully-auditable pieces:

| Module | What it fixes | The naive-backtest lie |
|---|---|---|
| `slippage` | Volume-aware slippage (half-spread + square-root impact) | "I filled 200k shares at the close price" |
| `fees` | Multi-market fees & taxes (US / TW / JP presets, all configurable) | "Commissions are round-off error" |
| `liquidity` | Participation-rate caps on executable quantity | "The market absorbed my 10× ADV order instantly" |
| `mae_mfe` | MAE/MFE excursion analytics | "The trade returned +5%" — but it dipped -8% first; would your stop have survived? |

Pure Python standard library. **Zero third-party dependencies.** Every model
is one short file you can read end-to-end before trusting it.

## Install

```bash
pip install friction-engine
```

Or from source:

```bash
pip install .
pip install ".[dev]"   # with pytest for running the test suite
```

## Quick start

```python
from friction_engine import (
    Market, Order, ParticipationCap, Side, TradePath,
    VolumeShareSlippage, excursion, fee_for,
)

order = Order(symbol="2330.TW", side=Side.BUY, quantity=20_000)

# 1. Liquidity: can the market absorb this?
allowed = ParticipationCap(0.10).cap(order, bar_volume=150_000)

# 2. Slippage: volume-aware fill price (not the close you assumed)
slip = VolumeShareSlippage(spread_bps=5, eta=0.5)
fill_price = slip.fill_price(order, 100.0, bar_volume=150_000, volatility=0.02)

# 3. Fees & taxes: TW stocks = 14.25 bps commission + 30 bps sell tax
fee, tax = fee_for(order, fill_price * order.quantity, market=Market.TW)

# 4. MAE/MFE: what happened inside the trade, not just entry→exit
path = TradePath(
    entry_price=fill_price, side=Side.BUY,
    highs=[101, 103, 106], lows=[97.5, 99, 102], exit_price=105.0,
)
rec = excursion(path)
print(rec.mae, rec.mfe, rec.giveback)   # -0.025 … +0.06 … how much you gave back
```

Run the full worked example:

```bash
python examples/basic_usage.py
```

## The models, honestly

**Volume-aware slippage** — `fill = ref × (1 + dir × (spread/2 + η·σ·√(q/V)))`.
The square-root temporary-impact shape is the most widely published
empirical form in the market-microstructure literature. `η` (eta) is a
calibration knob: 0.1 gentle, 0.5 typical, 1.0 harsh. If you don't know your
`η`, run all three and treat the spread of outcomes as your uncertainty.

**Fee presets** — US (zero commission + ~0.3 bps sell-side regulatory fees),
TW stocks (14.25 bps commission both sides + 30 bps sell tax), TW ETF
(10 bps sell tax), JP (10 bps commission + 10% consumption tax *on the
commission*, no share transaction tax). These are publicly documented
typical values as of mid-2026 and **will go stale** — brokers discount,
regulators re-price. Treat presets as starting points:

```python
from friction_engine import FEE_SCHEDULES, Market
my_tw = FEE_SCHEDULES[Market.TW].with_overrides(commission_bps=6.0, min_commission=20.0)
```

**Liquidity cap** — `min(quantity, max_participation × bar_volume)`. Simple,
brutal, and the single most common way backtests overstate capacity.

**MAE/MFE** — descriptive statistics over a trade's post-entry high/low
path (Sweeney-style excursion analysis). Aggregates (`excursion_stats`)
answer: *is my stop inside the noise band of my winners?* (`mae_of_winners_mean`)
and *how much do my losers climb before failing?* (`mfe_of_losers_mean`).

## What this library is NOT

- Not a backtester. It computes friction; you bring the loop, the data, and
  the point-in-time discipline. (Pair it with `quant-lint` to audit the
  strategy code feeding it.)
- Not a broker simulator. Fill *decisions* (partial fills, limit queues,
  halts) are out of scope; it prices the fills you assume.
- Not financial advice, and presets are not a fee-quote service. Verify
  current rates with your broker/exchange before trading real money.

## Development

```bash
python -m pytest            # run the test suite
```

Layout:

```
src/friction_engine/
  models.py      # Order / Fill / Side value types
  slippage.py    # Zero / Fixed / VolumeShare slippage models
  fees.py        # FeeSchedule + US/TW/JP presets
  liquidity.py   # ParticipationCap
  mae_mfe.py     # TradePath, mae/mfe, excursion, excursion_stats
tests/           # pytest suite, no network, no data files
examples/        # runnable worked example
```

## License

Apache-2.0 — see [LICENSE](LICENSE). Clean-room provenance: see
[CLEANROOM.md](CLEANROOM.md).
