# MACD crossover, simple and with a profit target and stop - frozen specification (RIP Backtest protocol v1.0)

Specification written **2026-10-07, before `mc_protocol.js` was run on any data.** Bugs may be fixed after the run; rules may not.

## The claim being tested
The MACD (moving average convergence divergence) is widely credited to Gerald Appel. Its most common use is the **crossover**: when the MACD line crosses above its signal line, momentum is turning up
(buy); when it crosses below, momentum is turning down (sell, or sell short). We found no single source for this exact rule set, so we describe it as a common setup and test our own exact definition at
the standard defaults (12, 26, 9), with nothing tuned.

## Instrument and data
ES futures, 60-minute bars built from our 1-minute data (bar time = close time, New York clock), 2020-01-01 to 2026-09-25. Costs: $5.76 commission per round trip and 1 tick ($12.50) slippage on every
fill, 1 contract, $50/point.

## Indicator
EMA(12) and EMA(26) of hourly closes (smoothing 2/(n+1), computed continuously from the first bar); MACD line = EMA(12) - EMA(26); signal line = EMA(9) of the MACD line. ATR(14) Wilder.
A **bullish cross** is a bar whose MACD is above its signal when the previous bar's was not above; a **bearish cross** is the mirror image. Signals are evaluated on bar close; market orders fill at the open
of the next 1-minute bar. Trading starts after 200 bars of history.

## Rules
- **Simple version (S), always follow the state:** be long while the MACD is above its signal line and short while it is below (long-only variant: long while above, flat while below). Every cross is a
  stop-and-reverse (exit and enter at the same fill). No stop, no target. Flat before the weekend (a Friday bar closing at or after 16:00 New York time exits, and no entries then); the position is re-taken
  at the first bar after the weekend according to the state.
- **Full version (F), enter on the cross:** enter on the bar of a bullish (or, for long-and-short, bearish) cross, when flat. Stop = 2 x ATR(14) (at the signal bar) from the entry fill, target = 4 x ATR(14),
  time limit 48 bars. Weekend flat. No signal exit. If target and stop could both have been touched inside the same 1-minute bar, the stop is assumed to hit first.

## Variants (declared up front; the ONLY ones tested)
MC-LS-S (long + short, simple), MC-L-S (long only, simple), MC-LS-F (long + short, full), MC-L-F (long only, full). Variants tried: **4**.

## Periods
Development 2020-01-01 .. 2023-12-31; Validation 2024-01-01 .. 2025-03-31; Holdout 2025-04-01 .. 2026-09-25.
The holdout is NOT unopened: this ES data was used in earlier tests of other strategies. It is reported, flagged as used.

## Gates (protocol v1.0, net of costs, per variant)
1. PF >= 1.2 in the validation period. 2. At least 50 trades in each period. 3. Development t-statistic >= 2.0 (four variants tried, so the base bar applies).
4. Above the 95th percentile of 500 random-entry runs. 5. Positive after removing the 10 best trades. 6. Holdout net positive (flagged used).

## Random-entry control
Same exits, session rule and costs, with the trade count calibrated to match the real variant. Simple versions: a random stop-and-reverse process (long-and-short) or random entries and exits with the same average
holding time (long only). Full versions: entries at random bars when flat, on a random side (long only for the long-only variant). 500 runs, fixed seeds. The statistic is the average net $ per trade over the full sample.

## Engine conventions (fixed before the run)
Identical to our other ES tests: a target fills at its price or at the bar's open if a 1-minute bar gaps through it; a stop fills at its price or at the open if gapped; costs apply to every fill; indicators are
computed continuously on the full series. Drawdown is reported both on closed trades and approximately including open losses (worst point reached inside each trade, from the 1-minute data).
The engine reproduces the published RSI(2) Dip Buyer trades exactly.

## Reading the result
Verdict labels follow the protocol: "No proven edge" means the test did not demonstrate a statistically convincing edge. It is not proof that none exists.
