Double top engine (reviewed version) self-test 2026-11-11T19:35:50.051Z [PASS] ATR(14) by hand: true ranges 2, 2, 1.3 (the third from the previous close), averaged while fewer than 14 bars: 2.0000 2.0000 1.7667 [PASS] ATR(14) by hand: Wilder smoothing from the 15th bar: (13 x 1 + 15) / 14 = 2: 1 2 [PASS] EMA50 by hand: closes 1..50 then 60: undefined before bar 49, 25.5 at bar 49, 25.5 + (2/51) x 34.5 at bar 50: 25.5 26.852941176470587 [PASS] zigzag by hand: pivots and the bars that confirm them (3% cut-off): T1@3 P6@8 T11@13 P16@18 T21@23 P26@28 T36@39 [PASS] double top by hand: valid (EMA50 rising from the first top to the second; tops 115 and 115.5 within $0.90), found when the second top is confirmed; the double bottoms fail the trend rule: 1:16-26 [PASS] double top by hand: N = the lowest low of bars 16..26 (103.8), top = the highest high (117), height 13.2, break at bar 32, target 90.6: N 103.8 top 117 h 13.200000000000003 b 32 target 90.6 [PASS] double top by hand: stop = the second top (highest high of bars 22..32, 116) + one tick = 116.01: stop 116.01 [PASS] pattern rule 1 by hand: EMA50 falling from the first top to the second -> rejected: rule failed: 1 [PASS] pattern rule 1 by hand: EMA50 equal at the two tops (not rising) -> rejected: rule failed: 1 [PASS] pattern rule 1 by hand: EMA50 rising elsewhere but higher at the first top than at the second -> rejected: rule failed: 1 [PASS] pattern rule 0 by hand: second top $0.89 above the first (inside 0.3 x 3 x $1 = $0.90) -> accepted: rule failed: 0 [PASS] pattern rule 2 by hand: second top $0.91 above the first -> rejected: rule failed: 2 [PASS] pattern rule 2 by hand: second top $0.91 below the first -> rejected: rule failed: 2 [PASS] the tolerance uses the ATR of the bar before the confirmation: ATR $0.50 at bar 27 (tolerance $0.45 < the $0.50 gap) rejects, ATR $0.50 at bar 28 does not [PASS] the tolerance scales with k: a $0.50 gap fails with k = 3 and ATR $0.50 ($0.45) and passes with k = 6 ($0.90) [PASS] time limit: the first close below N at bar 36, 10 bars after the second top (as many as from the first top) -> dropped: b -1 [PASS] time limit: the first close below N at bar 35 (9 bars after) -> taken: b 35 [PASS] the next pivot (a trough at 108, confirmed at bar 35 before any close below N) ends the pattern -> dropped: b -1 [PASS] a close below N on the bar that confirms the second top: the break is that bar: conf 27 b 27 [PASS] double bottom by hand (the mirror image, EMA50 falling): N = highest high 95.5, bottom 84, height 11.5, break at bar 32, target 107, stop = 84 - one tick = 83.99: N 95.5 bottom 84 h 11.5 b 32 target 107 stop 83.99 [PASS] double bottom with a rising EMA50: rejected by the trend rule [PASS] stop and target in the same minute: the stop is taken [PASS] a stop gapped through fills at the minute's open (98, not 99) [PASS] a target gapped through fills at the open (103, not 102) [PASS] the stop can be hit in the entry minute [PASS] short with the buffered stop 116.01: a high of 116.00 does not stop it, a high of 116.01 does [PASS] a pattern that breaks while a trade is open is ignored (not queued; the open trade unchanged); the next break after the exit is taken: 1:11-26 -1:31-34 1:51-60 [PASS] no trade when the entry is at the target or at the stop; such a break blocks nothing: {"target":1,"stop":1,"busy":1} [PASS] double bottoms only: no double top is traded [PASS] result in R: (direction x (exit - entry) - $0.30) / height; financing A and B; costs $0.45 and $0.75 as gross - cost / R [PASS] synthetic DT-1: engine and re-implementation agree trade by trade, and on the patterns found and broken: 128 vs 128 trades, 0 differences; patterns 271 vs 271, breaks 135 vs 135 [PASS] synthetic DT-2: engine and re-implementation agree trade by trade, and on the patterns found and broken: 46 vs 46 trades, 0 differences; patterns 80 vs 80, breaks 50 vs 50 [PASS] synthetic DT-3: engine and re-implementation agree trade by trade, and on the patterns found and broken: 66 vs 66 trades, 0 differences; patterns 271 vs 271, breaks 135 vs 135 [PASS] synthetic DT-4: engine and re-implementation agree trade by trade, and on the patterns found and broken: 23 vs 23 trades, 0 differences; patterns 80 vs 80, breaks 50 vs 50 [PASS] synthetic: the control at offset 0 reproduces the real trades: 128 of 128 [PASS] synthetic: double tops give shorts and double bottoms longs; double-bottom-only variants never short real data: 7067434 minutes, 129857 one-hour bars, 2004-06-11 01:19 .. 2026-10-07 16:57 New York (audit clock); patterns found k=3: 713 (broken 299), k=6: 255 (broken 118) [PASS] real data: the 1-hour bars equal a naive aggregation of the minutes (every 251st bar): 518 bars checked, 0 differences [PASS] real data: the volatility equals a naive recomputation (every 1001st bar): 0 differences [PASS] real data: EMA50 and ATR(14) equal the re-implementation's at every bar: 0 and 0 differences [PASS] DT-1: engine and independent re-implementation agree on every zigzag pivot, pattern, break and trade: 272 vs 272 trades, 0 differences; pivots 5588 vs 5588; patterns 713 vs 713; breaks 299 vs 299 [PASS] DT-1: control at offset 0 reproduces the real trades: 272 of 272, 0 differences [PASS] DT-2: engine and independent re-implementation agree on every zigzag pivot, pattern, break and trade: 107 vs 107 trades, 0 differences; pivots 2013 vs 2013; patterns 255 vs 255; breaks 118 vs 118 [PASS] DT-2: control at offset 0 reproduces the real trades: 107 of 107, 0 differences [PASS] DT-3: engine and independent re-implementation agree on every zigzag pivot, pattern, break and trade: 147 vs 147 trades, 0 differences; pivots 5588 vs 5588; patterns 713 vs 713; breaks 299 vs 299 [PASS] DT-3: control at offset 0 reproduces the real trades: 147 of 147, 0 differences [PASS] DT-4: engine and independent re-implementation agree on every zigzag pivot, pattern, break and trade: 52 vs 52 trades, 0 differences; pivots 2013 vs 2013; patterns 255 vs 255; breaks 118 vs 118 [PASS] DT-4: control at offset 0 reproduces the real trades: 52 of 52, 0 differences [PASS] no look-ahead: on the data cut at the end of a bar (4 cuts), every bar, indicator, pivot, pattern and trade completed before the cut is the same as on the full data: cut after 2011-04-19 06:00: 196 closed trades compared; cut after 2016-11-03 08:00: 305 closed trades compared; cut after 2022-05-12 16:00: 453 closed trades compared; cut after 2025-08-27 22:00: 533 closed trades compared [PASS] every broken pattern: first top, valley and second top confirmed one after another, the second top confirmed after it formed, the break at or after that confirmation; every entry after the break bar closed: 417 patterns, 0 out of order [PASS] hole windows: every end is the same minute (index) on gx_lib's clock and on the audit clock; labels differ only by the 0/60-minute moves: 2099 windows, 0 bad ends PASSED