# Double top and double bottom on XAUUSD, 1-hour bars - specification (RIP Backtest protocol v1.0 plus the 8 Oct 2026 rules)

Specification written and **frozen 2026-11-11 (approved by the owner the same day, "Da, îngheață și rulează"; draft 1 unchanged)**, before any zigzag, pattern, signal or trade of this test was computed on the gold data. 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-11-11: the double top pattern on 1-hour bars ("vreau sa facem asta acum double top pattern. citeste si fa tu take profit si stop loss. pe 1h"). Asked the same day, the owner picked **gold (XAUUSD)** out of gold, EUR/USD, GBP/USD and the ES/NQ futures, and said "citește" meant: read the commonly published rules and choose the entry, stop and target from them.
- **Rules as commonly published** (read 2026-11-11):
  - **Lo, Mamaysky and Wang** (Journal of Finance 55(4), 2000, Definition 5): a double top is two local maxima within 1.5% of their average (a gap of at most about 3%), at least 22 trading days apart, following Edwards and Magee; a double bottom is the mirror image.
  - **Bulkowski** (thepatternsite.com, the Eve & Eve double top, the classic form): an upward trend leading to the pattern; peaks that differ little, "often less than 3%"; a valley drop of at least 10% (a guideline he says he ignores); the pattern is **confirmed only when price closes below the valley** between the peaks (without confirmation price goes on higher 60% of the time); the **measure rule** projects the height from the highest peak to the valley downward from the breakout; 43% of his confirmed tops met the full target and 65% pulled back to the breakout price.
  - **Broker and education pages** (TastyFX, TMGM, Britannica Money, StockAlarm and others): enter on a **close below the neckline** (the valley's low); put the **stop above the second peak**; take profit at the **pattern's height projected from the neckline**.
  - These are the rules tested: one entry, one stop and one target, the most common of each. Exits by partial profit, a trailing stop or a retest entry are not tried, now or after the result.
- **The scale.** The published definitions are written for daily bars (22 trading days between the tops; gaps and valleys in percent of price). On 1-hour bars a percent of price means very different moves in 2004 and 2026, so the swings are measured in units of the market's recent volatility, with the zigzag of the **head-and-shoulders test on gold** (Osler and Chang's method, below). The 22-day separation is replaced by that zigzag: between the two tops price must fall and rise again by at least the zigzag's cut-off.
- **Earlier tests on this file:** the gold hub lists 18 strategies; none passed every gate. The closest relative is the **head-and-shoulders test on gold, 15-minute bars** (spec hs_spec.md, 16 Oct 2026): four variants, all buried; the long-and-short version at the smaller scale passed 5 of 6 gates (it failed only the development t, 1.26), at the 100th percentile of its control. That test is the reason for the bar below, and its results will be compared with these. **No double top or double bottom has been computed** on this file or any other in this workspace (search of the research folder and the project notes, 11 Nov 2026).
- **The development bar is t >= 2.5**: the chart-pattern family on this file now has eight variants (four head-and-shoulders, four here), and many strategies have been tried on this file (as in the CCI test of 8 Nov).
- Gold rose about elevenfold over the file, which favours long rules; long-only variants are included for that reason, as in the head-and-shoulders test, and the control trades the same direction at other times.

## Instrument and data
- **XAUUSD** on the IC Markets MetaTrader 4 demo server, a spot gold CFD in US dollars per ounce; 1-minute bid history from the first bar of 2004 to **2026-10-07 16:57 New York**, the part of the file read by the published gold studies.
- **Clock: the clock of our clock audit** (`gold_audit_clock.loadAuditClock`): the weeks the audit found an hour early (most weeks of 2004-2010, a few a year after) moved by +60 minutes, prices untouched (the rule of 11 Nov 2026 for every new test on these files). The pattern rules do not depend on the time of day; the control's "same time of day" does.
- **Bars:** 1-hour bars on the New York clock, closing on the hour, holding the 1-minute bars with close times in (t - 60 min, t] (`gh_lib.barsOf(M, 60)`), built from the minutes that exist; incomplete bars are kept as they are, empty ones do not exist. Positions are held over the daily break, weekends and holidays.
- **Data checks before the run** (`dtop_datacheck.js`, no pattern computed; any failure stops the test and goes to the owner):
  1. the first and last minute, and nothing after the cut;
  2. time stamps strictly increasing; the same minutes and prices as the uncorrected file, only the labels moved;
  3. days with data per year against the weekdays of the year;
  4. minutes on a Saturday, or after 17:00 New York on a Friday (reported; they would form short bars of their own);
  5. the US 08:30 New York data releases: in every year the mean absolute 1-minute move is larger at the minute stamped 08:31 than at 07:31 and 09:31 (on weekdays).
- **Holes (rule 3):** the suspect and unclear gaps of `data_holes_xau.json`. That file is on another clock (gx_lib's), so its windows are carried over to the audit clock minute by minute (the same minutes in the same order). Trades open across such a gap are counted, and every gate and verdict is recomputed without them; a changed verdict becomes Inconclusive.

## The pattern (on 1-hour closes)
- **Volatility:** s(t) = the standard deviation of the log changes between consecutive 1-hour closes over the 500 bars before bar t (about a month; gold trades about 23 hours a day), recomputed at every bar. Patterns are counted only after a warm-up of 500 bars.
- **Zigzag** (as in the head-and-shoulders test): a **peak** is confirmed at the first bar whose close is at least k x s(t) below (in log terms) the highest close since the last trough; a **trough** at the first bar whose close is at least k x s(t) above the lowest close since the last peak. The pivot's time and price are those of that highest (lowest) close, the first one if several are equal; the pivot is known only from the bar that confirms it (no look-ahead). The first move of k x s(t) after the warm-up decides the first pivot.
- **Two scales, k = 3 and k = 6**, as in the head-and-shoulders test. On 1-hour bars k = 3 finds patterns of a few days and k = 6 patterns of one to a few weeks.
- **Double top**, checked each time a peak is confirmed: the last five pivots are peak P0, trough T0, the **first top P1** (a peak), the **valley T1** (a trough) and the **second top P2** (the peak just confirmed). The pattern is valid if:
  1. **a rise before it:** P1 > P0 and T1 > T0 (a higher high and a higher low; the first rule of Osler and Chang's head and shoulders, as in that test);
  2. **equal tops:** the two tops' closes differ by at most 0.3 x k x s, in log terms (|ln(P2 / P1)| <= 0.3 x k x s(c), c = the bar that confirms P2). Bulkowski's gap of up to about 3% against a valley of at least 10% (and Lo, Mamaysky and Wang's 3%) put the gap at about 30% of the smallest valley; here the smallest swing is the zigzag's cut-off, k x s.
- **Levels, from the bars' highs and lows, as drawn on a chart:**
  - the **valley floor** (the neckline) N = the lowest low of the bars from P1 to P2, both included;
  - the **top** = the highest high of the same bars; the **height** h = top - N, in dollars per ounce.
- **Break (the confirmation):** the first 1-hour **close below N**, at or after the bar that confirms P2, provided that (a) the next zigzag pivot after P2 (a trough) has not been confirmed before it, and (b) it comes fewer bars after P2 than there are from P1 to P2 (the time limit of Osler and Chang's head and shoulders). Otherwise the pattern is dropped.
- **Double bottom:** the mirror image, checked each time a trough is confirmed (troughs and peaks swapped, every inequality reversed; the neckline is the highest high between the two bottoms, the break a close above it).

## The trade
- **Entry:** at the open of the first 1-minute bar after the break bar: a sell after a double top, a buy after a double bottom. One position at a time: a break that comes while a trade is open is not taken. The long-only variants ignore double tops.
- **Stop (above the second top):** for a sell, the highest high of the 1-hour bars from the bar after T1 to the break bar; for a buy, the lowest low over the same bars. No extra buffer.
- **Target (the measure rule):** N - h for a sell, N + h for a buy.
- **No trade** if the entry is already at or beyond the target, or at or beyond the stop.
- **Exits** checked inside each 1-minute bar from the entry minute on: if the stop and the target are both touched in the same minute, the stop is taken; a level gapped through fills at that minute's open. No time limit. A position open on the last bar is closed at its close and flagged.
- **R** (the unit of the results) = h, the pattern's height, as in the head-and-shoulders test: a trade that reaches its target makes about +1 R before costs (less the distance the entry already is beyond N). The distance to the stop is reported in R too.
- **Four variants:** **DT-LS-3, DT-L-3, DT-LS-6, DT-L-6** (double tops and bottoms / double bottoms only, long x zigzag scale k = 3 / k = 6).

## Costs
- **Baseline:** $0.30 per ounce per round trip, as in every gold test on the site; slippage zero, which is optimistic and stated.
- **Scenario A:** 3% a year of the entry price per calendar day held, longs and shorts alike. **Scenario B:** the IC Markets XAUUSD swap as recorded on 2026-10-12 (long -57.03, short +39.767 points per lot per night; Wednesday counting three), today's rate, not a historical one. The verdict is that of the baseline.

## Periods, gates, control
- **Periods (by entry date):** development 2004 to 2012; validation 2013 to 2019; holdout 2020 to 2026-10-07, **already used** by the earlier gold tests.
- **Six gates per variant:**
  1. validation profit factor >= 1.2;
  2. at least 50 trades in each period;
  3. development **t >= 2.5**;
  4. above the 95th percentile of 500 runs of the matched control;
  5. positive without the 10 best trades;
  6. holdout net positive (flagged as used).

  A variant with fewer than 30 trades is Inconclusive.
- **Matched control (moved entries, as in the head-and-shoulders test):** every real entry moved, all together, by one random circular offset of whole days (at least 5% of the days), to the same time of day on the new day, same direction; the stop and the target placed at the same distances from the new fill as in the real trade, **measured in units of the volatility** (s x close of the last 1-hour bar closed before the entry), so that a pattern of 2004 moved to 2024 keeps its size relative to the market; R scaled the same way; same costs and one-position rule. 500 runs, seeds 1000 + run. Statistic: the average net R per trade. It asks whether the pattern's breaks pick better moments than the same trades placed at other times.

## Engine and self-test (before the run)
New code: `dtop_lib.js` (the engine, reusing the head-and-shoulders engine's volatility, zigzag, exits and control), `dtop_ref.js` (an independent re-implementation: its own bars, volatility, zigzag, patterns and walk) and `dtop_selftest.js`, which must pass before any result is printed:
1. hand-worked cases on made-up prices: the volatility; the zigzag (confirmation, equal closes, the cut-off changing with s); each pattern rule accepting and rejecting (the rise before, the equal-tops tolerance at its edge); the valley floor, the top and the height from highs and lows; the break at the confirming bar and later; the time limit; a pattern dropped when the next pivot comes first; the double bottom; the entry at the next minute; a trade skipped at or beyond its target; the stop and the target, both in one minute (stop taken), in the entry minute, gapped through; one position at a time; long only ignoring tops; R, costs and the two financing scenarios;
2. the 1-hour bars against a naive aggregation of the minutes;
3. the re-implementation matched trade by trade for all four variants on the real data;
4. the control at offset 0 reproducing the real trades;
5. the hole windows carried over to the audit clock, checked on a sample by hand.

## Before the article
Results go to the owner first: all four variants and every gate, with the verdict and its cause; tops and bottoms separately; by year; the patterns found per year and per scale, and the share of them that broke the valley in time (Bulkowski: without confirmation, price goes on 60% of the time); the share of trades reaching the target and the stop (his 43% meeting the target); the share that came back to the valley floor before the exit (his 65% pullback rate); the average height in dollars and the cost per trade against the gross; time in trade; both financing scenarios; the hole check; the comparison with the head-and-shoulders test. 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 market, one timeframe, one broker's demo history, one mechanical definition of the pattern at two scales; traders who pick double tops by eye may select differently.

### Run log
- 2026-11-11: frozen. sha256 of this file above the "### Run log" heading: 259aebcc3a7f534755adda44792a7db29124ca307c123dbbf16fa1f89ac771de.
- 2026-11-11, before the run: dtop_datacheck.js passed every check (first minute 2004-06-11 01:19, last 2026-10-07 16:57 New York, nothing after the cut; the audit clock moves 1,793,066 minute labels by 0 or 60 minutes, same minutes and prices as the uncorrected file; 253-259 forex days in every full year; 55 minutes after 17:00 on a Friday, on 2010-01-22 and 2015-01-02 only; the 08:31 minute has the largest move of 07:31 / 08:31 / 09:31 in every year on the audit clock, while on the uncorrected file 07:31 is the largest in 2004-2010; all 2,099 hole windows carried over to the audit clock). Outputs dtop_out/dtop_datacheck.txt and dtop_holes_audit.json.
- 2026-11-11: dtop_selftest.js PASSED on its first run (45 checks; engine = re-implementation on every zigzag pivot, pattern, break and trade of the four variants on the real data; the control at offset 0 reproduces every trade). dtop_run.js -> dtop_out/: DT-LS-3 151 trades, avg -0.020 R (gross +0.006), control percentile 49.6, Buried 1/6; DT-L-3 75 trades, +0.089 R, 67.6, Buried 2/6; DT-LS-6 60 trades, +0.095 R, 80.4, Buried 1/6; DT-L-6 31 trades, +0.141 R, 59.8, Buried 1/6, and by rule 3 Inconclusive (19 of its 31 trades are open across a suspect or unclear gap; the 12 left are fewer than the 30 a verdict needs). No rule was changed.
- 2026-11-11, after the run: the owner pasted an outside review of this specification's draft and asked for it to be applied, frozen and run ("aplică întâi recenzia, apoi îngheață și rulează"). Done as a separate test, dtop2_spec.md (EMA50 trend, ATR(14) tolerance in dollars, a one-tick stop buffer, DT-1..DT-4); this version's results stand and are reported with it. A no-look-ahead check (the engine on the data cut at four points gives the same pivots, patterns and trades for everything completed before each cut; every traded pattern's pivots confirmed in order) was added to dtop_selftest.js and PASSED; no rule or result changed.
- 2026-11-12: published as /posts/double-top-pattern-gold/, beside the reviewed version (dtop2_spec.md), which is the main result.
