# Intraday Trend Pullback on Bitcoin (BTCUSDT, 15-minute bars) - specification (RIP Backtest protocol v1.0 plus the 8 Oct 2026 rules)

Specification written and **frozen 2026-10-14 (approved by the owner the same day, draft 1 unchanged)**, before any EMA, signal or trade of this rule was computed. Once frozen, any change of a rule is documented and treated as a separate test; bugs may be fixed.

## Why this test, and what was looked at before
- **Chosen by the owner** on 2026-10-14 ("Intraday Trend Pullback on BTC"), with the choices made the same day: 15-minute entries, the trend on 1-hour bars, a cost of 0.05% per fill, two variants (long and short, long only) with a 2R target.
- "Trend pullback" has no single published rule; this specification fixes one common mechanical version (trend from two moving averages on a higher timeframe, entry when price closes back above a short moving average after a dip to it, stop below the pullback, target at twice the risk, flat by the end of the day). The article will say it is our version.
- The only earlier use of this Bitcoin file is the daily Turtle test (2026-10-12 to 14), which looked at 20- and 55-day breakouts; no intraday number, EMA or pullback was computed. **The holdout (2024 to September 2026) was opened once before, by the Turtle test**, and is reported as used once.

## Data
- The same Binance BTCUSDT 1-minute file as the Turtle test (`BTCUSDT_1min.csv`, SHA-256 `e52154201bd4b0552f9649036d53e8bfcf8897590e9265e665b0fef4616ed415`, 2017-08-17 04:00 to 2026-09-30 23:59 UTC), UTC clock, minutes stamped at their close.
- **15-minute and 1-hour bars** on the UTC clock (15-minute bars start at :00, :15, :30, :45; 1-hour bars on the hour), built from the minutes that exist; a bar with no minutes does not exist and is skipped.
- **Holes (rule 3):** trades open across a gap of 10 minutes or more in `btc_gaps.json` are counted, and every gate and verdict is recomputed without them; a changed verdict becomes Inconclusive.

## Rules
- **Trend (1-hour):** EMA(50) and EMA(200) of the 1-hour closes (each seeded with the simple average of its first values). Up trend: EMA50 > EMA200; down trend: EMA50 < EMA200. A 15-minute bar uses the trend of the **last 1-hour bar closed at or before its own close** (a 15-minute bar closing at 10:15 uses the 1-hour bar that closed at 10:00): no look-ahead.
- **Pullback and signal (15-minute):** EMA(20) of the 15-minute closes. **Long signal** at the close of 15-minute bar k: the trend is up, the close of bar k-1 was at or below its EMA20 (the pullback), and the close of bar k is above its EMA20. **Short signal:** mirror (trend down, close k-1 at or above EMA20, close k below).
- **Entry:** at the open of the first minute after the signal bar (the next bar's open), if no position is open.
- **Stop:** one tick ($0.01) below the lowest low of the last five 15-minute bars up to and including the signal bar (shorts: one tick above the highest high). *(Implementation note added during the engine self-test, 2026-10-14, before any result: stop levels are rounded to the cent, as prices are quoted in cents; without it floating-point subtraction leaves the stop a fraction of a cent off.)* If the entry price is already at or beyond the stop, there is no trade. **Risk R** = |entry - stop|.
- **Target:** entry + 2R (shorts: entry - 2R).
- **Execution on 1-minute bars:** after the entry minute, each minute checks the stop first, then the target (the cautious order when one minute touches both); in the entry minute only the stop is checked. A level gapped through fills at the minute's open.
- **End of day:** a position still open is closed at the close of the 23:59 UTC minute. Signals after that start new trades on the next day.
- **One position at a time;** signals while a position is open are ignored; after an exit a new signal can come from the next 15-minute bar.
- **Warm-up:** signals are counted from **2017-09-15 00:00 UTC** (at least 600 hours after the first bar, so EMA200 is settled).
- **Two variants:** **BTC-TP-LS** (long and short) and **BTC-TP-L** (long only).

## Costs and results
- **Costs: 0.05% of the price on every fill** (entry and exit), about 0.1% a round trip: the taker fee on Binance USD-margined perpetual futures, where shorts are possible. Slippage zero beyond gaps, which is optimistic and stated.
- **Funding (scenario, not the verdict):** perpetual futures charge funding every 8 hours (00:00, 08:00, 16:00 UTC). Scenario A charges longs and credits shorts **0.01% of the price at each 08:00 and 16:00 UTC** the position is held (Binance's default rate; real rates varied, often higher in strong markets): not a historical series.
- **Unit of the results:** the **net result in percent of the entry price** per trade (the same as dollars per $100 traded); gates use it. Results in R are reported next to it (a trade with a very small R can show a large loss in R from costs alone, so R is not used for the gates).

## Periods, gates, control
- **Periods (by entry date):** development 2017-09-15 .. 2021-06-30; validation 2021-07-01 .. 2023-12-31; holdout 2024-01-01 .. 2026-09-30 (**used once before**, by the Turtle test).
- **Six gates per variant:** validation profit factor >= 1.2; at least 50 trades in each period; development **t >= 2.0** (two variants of a strategy not tested before on this site); above the 95th percentile of 500 runs of the matched control; positive without the 10 best trades; holdout net positive (used once). Fewer than 30 trades: Inconclusive.
- **Matched control (moved entries):** every real trade's entry moved, all together, by one random circular offset of at least 5% of the days, to the same time of day on the new day, same direction; the stop is placed at the same distance in percent from the entry, the target at 2R, with the same end-of-day exit, one-position rule and costs. 500 runs, seeds 1000 + run. Statistic: the average net percent per trade. It asks whether the pullback signal picks better moments than the same trades placed on other days.

## Engine and self-test (before the run)
A new engine (`tp_lib.js`) and a self-test that must pass before any result is printed:
1. Hand-worked cases: EMAs and their seeds; the 1-hour trend used by a 15-minute bar (no look-ahead); a long and a short signal; entry at the next open; the stop below the five-bar low; no trade when the entry is beyond the stop; the stop and the target, the cautious order in one minute, a gapped fill; the end-of-day exit; one position at a time; costs and the result in percent and in R; the funding scenario.
2. 15-minute and 1-hour bars against a naive grouping of the real minutes.
3. An **independent re-implementation** matched trade by trade for both variants on the real data.
4. The control at offset 0 reproduces the real trades.

## Before the article
Results go to the owner first: both variants, every gate, long and short separately, by year, by time of day, how trades ended (stop, target, end of day), the cost per trade against the gross, the funding scenario, the hole check. One article, published only with the owner's agreement.

## Reading the result
"Buried" or "Inconclusive" mean a statistically convincing edge was not demonstrated; neither is proof that none exists. One version of a loosely defined idea, one exchange's data, one set of parameters.
