# London open breakout on XAUUSD versus a random control

This is a test record, not advice. Do not trade on it.

**Question.** On XAUUSD in 2026, does buying or selling the first 1-minute close outside the
00:00–06:59 UTC range, between 07:00 and 09:59 UTC, with symmetric barriers at half the range,
earn more per trade after real spread than random entries with the same exits?

**Kill rule (written 2026-09-05, before the data was complete).** Killed if the rule's mean net
P&L per trade is not above the random control's mean by at least two standard errors of the
control distribution, or if the January–April and May–August halves disagree in sign. Fewer
than 100 trades means inconclusive, not survived.

The full rule, exits and control are in the docstring of `backtest.py` and in the experiments
entry `site/src/content/experiments/2026-09-05-london-breakout-gold.md`. Nothing was tuned.

## Data

Dukascopy tick data, XAUUSD, 2026-01-02 to 2026-08-31, bid and ask, fetched with
`research/dukascopy/fetch.py` into `~/data/dukascopy/XAUUSD/` on the server (not committed) and
aggregated to 1-minute bars with `research/dukascopy/bars.py` into `~/data/bars/XAUUSD_m1.csv`.
Coverage is checked per day: a day counts only if the range window has at least 300 one-minute
bars and there is a bar at or after 16:00 UTC.

## Result (2026-09-05)

**Killed** by the pre-registered rule. Run on the MetaTrader tick export (`~/data/ticks/XAUUSD.r/`,
converted with `../dukascopy/bars_mt5.py`, broker clock UTC+2/+3 verified against Dukascopy ticks
in January and August), because the Dukascopy download was throttled to hours. 169 trading days,
89 trades, mean +5.05 USD/oz vs control −0.21 ± 3.43 (excess 1.5 s.e., rule asked for 2); both
halves positive (+0.3 and +2.3 s.e.). Full table and trade list in `result.md`.

`trades.csv`, written beside `result.md` by the same run, is those trades one row each for
trade-by-trade comparison: `day`, `direction`, `signal_bar_utc`, `entry_fill_utc`, `entry_price`,
`exit_utc`, `exit_price`, `exit_reason`, `pnl`. Every timestamp is UTC ISO 8601 with `+00:00` and
names the bar's opening minute: `signal_bar_utc` is the bar whose mid close broke the range,
`entry_fill_utc` the *next* bar, whose ask open (long) or bid open (short) is `entry_price`, and
`exit_utc` the bar that triggered the exit — a barrier touch, priced at the barrier level the P&L
assumes, or the first bar at or after 16:00 UTC, priced at its bid open (long) / ask open (short).

Next, if anything: the identical test on 2023–2025 before changing any parameter.

## Run

```
~/.venv/bin/python ../dukascopy/bars_mt5.py XAUUSD.r ~/data/bars/XAUUSD_mt5_m1.csv
~/.venv/bin/python backtest.py ~/data/bars/XAUUSD_mt5_m1.csv --series 1000 --seed 1
# or, from Dukascopy once the cache is complete:
python3 ../dukascopy/fetch.py XAUUSD 2026-01-01 2026-08-31 --workers 2   # resumable
python3 ../dukascopy/bars.py  XAUUSD 2026-01-01 2026-08-31
python3 backtest.py ~/data/bars/XAUUSD_m1.csv --series 1000 --seed 1
```
