One Decision, Four Rulers: Re-measuring the Window Length of My Gold EA
This is the fifth entry in the incubation diary for my gold breakout EA. The EA places a buy stop at the highest high and a sell stop at the lowest low of the last N closed M15 bars, only during 10:00 to 13:59 UTC, with an initial stop of 0.5 ATR and a trailing exit. The live version uses N = 128, which is 32 hours of M15 bars. This entry is about how that number was chosen, what it bought, and how much of the original case for it survived after I fixed the way my simulator counted trades.
The short version: widening the window from 32 bars to 128 bars is still the biggest single lever I have found for this EA, and it points the same way under every version of my simulator. But the size of the improvement I first wrote down was mostly an artifact. Measured with the simulator that matches the EA, the lever takes the strategy from clearly losing to roughly break-even, not from good to excellent.
Why the window, and not the cost
By early August I had spent several experiments trying to reduce what each trade costs: stop-limit orders instead of plain stops, limit entries on a pullback after the break, and stops anchored to the breakout level instead of the entry. All three failed when measured. The cost of a breakout trade on gold at my broker is roughly a fixed spread component plus a part that scales with volatility, and my model of it is $0.247 plus 0.0653 times ATR per round trip. The fixed part is the measured session spread, and the proportional part came from matching simulated fills against real ticks. I have not found an execution trick that makes it smaller without also removing the trades that pay for it.
If the bill per trade cannot be cut, the other option is to make each trade worth more before the bill arrives. A longer Donchian window puts the entry level further from the current price, so a breakout has to travel further to trigger, and the hope is that the moves which do trigger are larger relative to ATR. That was the hypothesis.
One decision, four rulers
The first time I ran the comparison, on 4 August, Session A looked like this: 32 bars gave +0.0656 R per trade, 128 bars gave +0.4154. More than six times better. I switched the EA to 128 on the strength of that table.
That simulator had a counting error, which I described in the second entry of this diary (Seven Checks, Two False Passes). It kept each pending stop alive for 240 minutes. The real EA deletes and re-places all of its pending orders on every new M15 bar, so a stop order in the live terminal lives for 15 minutes. With a four-hour order life, the same breakout could be recorded from several signal bars, on average 4.3 times per real fill. The duplication was not neutral: a level that stayed unbroken for a long time and then broke cleanly produced more copies, and those were disproportionately the good trades.
Fixing that took more than one step, and each step moved the 128-bar number. What I had not done until this week was go back and re-measure the original 32-versus-128 decision at each step. Here it is, all Session A, XAUUSD, 2010 to mid-2026, same trailing exit, same cost model, R net of cost and measured against the initial 0.5 ATR stop:
| Simulator version | 32 bars, R per trade | 128 bars, R per trade |
|---|---|---|
| Earliest version (4 August) | +0.0656 | +0.4154 |
| Later revision, still 240-minute order life | -0.0203 | +0.3181 |
| 15-minute order life, window as a closed interval | -0.1296 | +0.0601 |
| 15-minute order life, strict half-open interval (matches the EA) | -0.1614 | +0.0068 |
The first two rows differ for reasons unrelated to duplicate counting; the simulator went through other revisions in between. The third row removes most of the duplication. The fourth closes a last gap: with a closed 15-minute interval, two adjacent signal bars can both claim the same M1 bar, which is still a double count. The last row is the one I published in the second entry and the one now in the EA header, so it is the one I use for the rest of this entry.
Two things are true at once in that table. The direction held on every row: 128 bars beat 32 bars under every ruler I have used. And the level collapsed: the configuration I chose because it looked like +0.42 R per trade measures +0.0068 once the counting matches what the EA does.
The full sweep under the strict simulator
I re-ran the window sweep this week with the strict simulator and first checked that the 128-bar row reproduced the published figure exactly (6,576 trades, +0.0068 R per trade). The sample covers 16.5 years across 17 calendar years.
| Window (M15 bars) | Trades | R per trade | Positive years | Max drawdown (R) |
|---|---|---|---|---|
| 32 (8 h) | 14,691 | -0.1614 | 2 of 17 | 2,391 |
| 64 (16 h) | 11,190 | -0.1134 | 4 of 17 | 1,399 |
| 96 (24 h) | 7,358 | -0.0073 | 8 of 17 | 615 |
| 128 (32 h) | 6,576 | +0.0068 | 8 of 17 | 521 |
| 144 (36 h) | 6,339 | +0.0077 | 8 of 17 | 516 |
| 192 (48 h) | 5,173 | +0.0174 | 8 of 17 | 417 |
| 256 (64 h) | 4,650 | +0.0179 | 8 of 17 | 423 |
| 320 (80 h) | 4,030 | +0.0167 | 8 of 17 | 356 |
| 448 (112 h) | 3,368 | +0.0057 | 9 of 17 | 317 |
| 640 (160 h) | 2,755 | -0.0429 | 9 of 17 | 274 |
| 960 (240 h) | 2,223 | -0.0586 | 10 of 17 | 239 |
At 32 bars the strategy is not a weaker version of itself; it is a clearly losing one, with 2 positive years out of 17 and a drawdown of almost 2,400 R across the sample. From about 96 to 448 bars the result sits on a flat shelf between -0.007 and +0.018 R per trade, and beyond that it falls away again. The best cell, 256 bars, is ahead of 128 by about 0.011 R per trade, which is well inside the noise of an eleven-setting sweep on one data set, so I did not move the EA.
The shape matters more to me than the best cell. If the EA only worked at one exact window length, I would treat 128 as a fitted number. Instead there is a wide plateau and 128 sits on it, and the optimum is inside the searched range rather than pinned to its edge. In separate work on a different gold breakout design, the best window kept landing on the boundary of whatever range I searched, which is usually a sign the parameter is not controlling what you think it controls. That did not happen here. It is a small point in favour of the window being a real lever. It is not a point in favour of the strategy being profitable, because the plateau is at zero.
Where the improvement comes from
Here are the same four short windows, with gross result and cost each expressed as a total divided by total ATR at entry:
| Window | Gross / ATR | Cost / ATR | Trades per year |
|---|---|---|---|
| 32 | 0.0892 | 0.1690 | 890 |
| 64 | 0.1243 | 0.1749 | 678 |
| 96 | 0.1652 | 0.1734 | 446 |
| 128 | 0.1748 | 0.1739 | 399 |
The cost column is flat because the same cost model is applied to every window; it can only move with the average ATR at entry, and that barely changes. So the cost column is not evidence of anything. The gross column is. It almost doubles, from 0.089 to 0.175, and that is the part of the hypothesis this table can test. It held: a longer window does select larger moves relative to volatility.
One caveat runs in the 32-bar row's favour. The proportional cost of 0.0653 ATR was calibrated on a 64-bar configuration. An earlier estimate, made when the EA still used 32 bars, had put the proportional part near 0.125 ATR. If that earlier figure is closer to the truth for short windows, the 32-bar row is flattered here, and the real gap is wider.
The same table also shows the uncomfortable part. At 128 bars, gross is 0.1748 and cost is 0.1739. The window doubled what each trade earns before costs and brought it up to almost exactly the size of the bill. The gap between them is less than one thousandth of an ATR per trade (this ratio of totals weights high-volatility trades more heavily than the per-trade average does, which is why it comes out smaller than the +0.0068 R figure would imply). In the fourth entry of this diary I measured 25 live fills and found every one of them filled worse than the order price, with a median of $0.190, about 4.3 percent of the stop distance at the time. A single median fill like that is many times larger than the entire gap between gross and cost in the table above.
The two halves of the sample
| Window | R per trade, 2010 to Jan 2018 | R per trade, Feb 2018 to 2026 |
|---|---|---|
| 32 | -0.0787 | -0.2335 |
| 64 | -0.0171 | -0.1969 |
| 96 | +0.1364 | -0.1300 |
| 128 | +0.1557 | -0.1172 |
The window improves both halves, but not equally: from 32 to 128 bars, the early half gains about +0.23 R per trade and the recent half about +0.12. It does not turn the recent half positive. Under the strict simulator, every window from 32 to 960 bars is negative after February 2018, between about -0.11 and -0.23 R per trade. The 16.5-year average of +0.0068 at 128 bars is the combination of a positive early period and a losing recent one.
One split point is one split point, and a strategy that depends on the size of rare large moves can have long flat or negative stretches, so this does not by itself prove the entry is worthless. It does show that the full-sample average is not a fair description of what this configuration has been doing recently, and that the window change, whatever its value, does not close that gap.
What I got wrong, specifically
I made the window decision on a table that was inflated by duplicate counting. When I corrected the simulator, I re-measured the 128-bar configuration but did not re-measure the decision that produced it. That left an unchecked assumption under the live EA: that 128 was better than 32 by the margin I had originally recorded.
Re-running it this week, the gap between 32 and 128 turned out to matter more than I thought, because it is now the difference between a losing configuration and a break-even one. The level at 128 is far lower than I thought. I only know both of those things because I re-ran the old comparison rather than trusting it.
The rule I am taking from this is simple and a little tedious. When the measuring tool changes, every decision made with the old tool is unverified until it has been measured again with the new one. Correcting the headline number is not enough; the choices that produced the headline number need the same treatment.
Where this leaves the EA
The forward test continues on a demo account with the 128-bar window. I am not changing the window: the strict sweep gives no reason to prefer another point on the plateau, and changing a live parameter would reset the forward record.
What this entry changes is how I read that forward record. The honest expectation for the current configuration is an average that is not distinguishable from zero over a long history, with a negative recent half, and gross earnings that only just cover the modelled cost. A few weeks or months of live trades cannot confirm or reject something that close to zero. The more useful thing the forward test can do is measure the cost side directly, because that is where the result will be decided. The model assumes $0.247 plus 0.0653 ATR per round trip, which at an average ATR of about $9.5 (the twelve months to early August) is nearer 0.09 ATR than the 16.5-year average of 0.174. If the live cost per trade drifts meaningfully above the model, there is nothing left for the entry to deliver. I use my free Execution Caliper utility for exactly this kind of comparison, between what a strategy's stop distance can afford and what the account actually charges.
There are other candidate changes in my notes, including a filter on how far price is from the breakout level when the order is placed. It looks strong in the M1 simulation and was inconclusive in a first real-tick check. I am deliberately not applying it to the live EA. It was found by searching the same sixteen years that produced every other number here, and it has not been through the out-of-sample and multiple-testing checks I committed to before any parameter change.
Next entry: how long this forward test would need to run before it could say anything statistically meaningful, once the trades are counted as independent breakouts rather than as individual fills.


