# TR-Keltner — Rules (own words, not a transcript copy)

- Official source article: `https://tradingrush.net/i-risked-keltner-channel-trading-strategy-100-times/`
- Accessed: 2026-09-29. No video transcript is used here; the article is the source.
- Scope of this file: what the article was observed to say, what we assume, and what
  stays open. This is a mechanical variant of the article's idea, not an exact
  replication of its 100 manual trades.

## Article claim (as stated in the article, not our measurement)

- About 100 manual backtest trades on 30-minute charts.
- Reported win rate approximately 49% at a fixed 1.5:1 reward-to-risk.
- Long entry after a candle closes fully above the upper Keltner band; short mirror
  below the lower band.
- The article leaves the channel parameters and the stop rule undefined: no EMA
  length, no ATR length or multiplier, and no stop placement beyond the fixed 1.5R
  target framing.

## Observed strategy rules (paraphrased)

1. Keltner channel: an EMA midline with ATR-based upper/lower bands.
2. Long signal: a candle whose body sits fully above the upper band (open and close
   both above it). Short mirror below the lower band.
3. Exit framing: fixed 1.5R target; the stop side is not specified precisely enough
   to copy.

## Differences to the source (why no exact replication is claimed)

- The 100 trades were manual picks on 30m charts with undisclosed dates, symbols,
  channel settings and stop rule; here H1, full 2017-2026 window, no cherry-picking.
- Channel parameters are undefined in the article, so we freeze one standard reading
  (EMA20, ATR20, 2.0 multiples, all on prior completed bars) and vary the multiplier
  once (`k15`).
- The stop is undefined in the article, so we freeze an explicit capped rule (A6):
  the opposite band when it is within 2.0 ATR, otherwise a fixed 1.0 ATR stop.
  Neither branch claims to be the article's stop.
- The article's medium is 30m; this test runs H1 per assignment scope.

## Explicit frozen assumptions for this test

| # | Point | Frozen default | Reason |
|---|-------|----------------|--------|
| A1 | Midline | EMA20 on close | Standard Keltner reading; article gives no value |
| A2 | Bands | +/- 2.0 x ATR(20, Wilder) | Standard Keltner reading; article gives no value |
| A3 | Causality | Bands at bar `i` use closes up to and including bar `i` only (prior completed bars, no lookahead) | Testable, reproducible |
| A4 | Entry event | Fully closed candle: long requires `open[i]` AND `close[i]` strictly above the upper band (on-the-band is not outside); short mirror | Literal "open and close both above" |
| A5 | Target | 1.5 x (entry - stop), set at order time | Article's stated 1.5:1 ratio |
| A6 | Stop | Opposite band on the signal bar when within 5.0 x ATR(20) of the signal close, else a fixed 1.0 x ATR(20) stop from the signal close | Justification: at a 2.0-wide channel the opposite band is at least 4 ATR away by construction, so a tighter cap would make the band branch dead code; beyond 5 ATR the band stop puts the 1.5R target 7.5+ ATR away (near-unreachable, R meaningless). The cap preserves band logic for tight breakouts and keeps risk bounded for extended ones |
| A7 | Bar decision timing | Closed bars only; fill at the next bar's open | Avoids intra-bar repaint |
| A8 | Overlapping signals | One position per symbol; signals while open ignored | Same convention as existing tests |
| A9 | Costs | Fixed assumed costs (bid-only data): spread EURUSD 1.0 pip / EURJPY 1.2 pip (half-spread adverse per fill) plus $7/lot round trip ($0.07 at 0.01 lot); EURJPY commission converted at fixed USDJPY 140 | Assumptions, not measured costs |
| A10 | Period / split | Full Dukascopy H1 window from 2017 per symbol, predeclared IS/OOS split at 2024-01-01 00:00 UTC+2 (trades assigned by exit time) | W7-TEST requirement |

## Open points and variant plan (at most three variants including base)

| # | Open point (source silent or ambiguous) | Base (above) | Variant (`test.py` id) |
|---|----------------------------------------|--------------|------------------------|
| V1 | Channel width unknown | 2.0 x ATR | `k15`: 1.5 x ATR channel (same stop rule) — rerun both symbols |

One single-dimension variant; it reruns the full two-symbol battery so the reported
range reads "depending on open point X, the measured win rate lies between A and B".
The article's manual 100-trade sample cannot be reconstructed; no exact replication
is claimed.

Reproduce with `py -3.11 test.py` (vectorbtpro). Outputs are in `results/`.
Engine: signal/execution conventions and cost model are shared with the existing
`w7_vbt.py` harness (imported, not modified); every ledger trade is replayed in
vectorbtpro at exact fills (see `vbt_reconciled` in `results/summary.csv`).
