# Historical Replay, Coin-Leakage, and Parameter-Sweep Pattern

Use this pattern when a paper-trading tournament is too slow because entry signals are rare, or when an apparently strong strategy might be overfit to one coin or short market window.

## Goal

Move from "one promising bot version" to an evidence pipeline:

1. Reconstruct historical strategies as parameter presets, not old executable commits.
2. Run side-effect-free historical replay over cached exchange candles.
3. Split replay into walk-forward segments to detect unstable performance.
4. Attribute performance by coin and exit reason.
5. Run leakage checks to see whether one asset explains the edge.
6. Run parameter sweeps around the best candidate to find robust zones, not magic constants.
7. Promote the sweep winner to a new paper-only candidate preset, then validate live in isolated paper trading.

## Implementation shape

Add or extend a replay module with pure functions and dataclasses:

- `Candle`
- `ReplayTrade`
- `ReplayResult`
- `WalkForwardResult`
- `TradeBreakdowns`
- `run_replay_for_preset(...)`
- `run_walk_forward_tournament(...)`
- `aggregate_trade_breakdowns(...)`
- `run_coin_slice_replay(...)`
- `run_parameter_sweep(...)`
- `render_walk_forward_report(...)`
- `render_parameter_sweep_report(...)`

Keep the replay engine side-effect-free except for explicit CLI/report/cache boundaries. It must never place orders, mutate live config, or read secrets.

## Candle cache

Fetch candles into a runtime cache under a user-local state directory, e.g.:

```text
~/.local/state/<BotName>/candle_cache/
```

Reports belong under:

```text
~/.local/state/<BotName>/reports/
```

Do not store replay cache, journals, or reports in Git.

## Walk-forward report

For each strategy report:

- aggregate score
- stability score = fraction of positive segments
- closed trades
- win rate
- average PnL
- total PnL
- max drawdown
- profit factor
- per-segment PnL
- top coins by PnL
- exit-reason stats
- `observation-only` marker when sample size is too small

Example output shape:

```text
Historical Replay Tournament
Mode: walk-forward
1. candidate_x: score=+1.14, stability=1.00, n=5, win=0.80, total=+1.50, max_dd=-0.17, pf=9.83, segments=[+0.07, +0.62, +0.82]
   coins: WLD:n=4,total=+1.44,win=0.75; HYPE:n=1,total=+0.07,win=1.00
   exits: Dead Fish Time-Stop:n=2,total=-0.10; V-Shape Trail Exit:n=3,total=+1.61
```

## Coin-leakage checks

When a candidate wins, immediately rerun slices such as:

- all coins
- without the apparent strongest coin
- majors only
- alts only
- alts excluding the strongest coin

If the edge disappears without one coin, label the candidate as promising but fragile. Do not treat it as live-ready.

## Parameter sweep

Sweep around the current champion rather than blindly optimizing the entire search space. Typical axes for flash-crash rebound bots:

- `flash_crash_trigger_pct`: e.g. 3.5 / 4.0 / 4.5 / 5.0
- `dead_fish_time_limit_mins`: e.g. 25 / 40 / 60
- `v_shape_trail_dist_pct`: e.g. 0.5 / 0.75 / 1.0

Rank variants by risk-adjusted score plus stability. Promote a candidate only when it improves both aggregate score and walk-forward stability.

## Promotion rule

If a sweep winner beats the champion, register it as a new paper-only preset with a new candidate ID, e.g.:

```text
candidate_v63_<descriptive-name>
```

Include `source="candidate:parameter-sweep:<date>"` and tags such as:

```text
candidate, sweep-winner, loose-rebound, fast-decay
```

Then restart the paper tournament with:

- the new candidate
- previous champion
- best historical controls
- at least one conservative baseline

## Guardrails

- Never live-trade based on replay alone.
- Keep small samples observation-only.
- A high profit factor from 3-5 trades is a clue, not proof.
- One-coin performance is a leakage warning, even when profitable.
- Parameter sweeps can overfit; prefer robust plateaus over one peak.
- Use TDD for new replay/sweep APIs before implementation.
- Run tests, compile checks, and safety scans before commit/push.
