# Market Flow Research — full text of all 83 articles Source: https://marketflowresear.ch/ · built 2026-10-28. AI-assisted research, human-reviewed. Research, not financial advice. ================================================================================ # The Pair That Behaves the Same on Three Stretches of Data — How the Live Bot's Networks Were Chosen URL: https://marketflowresear.ch/articles/the-pair-that-behaves-the-same-on-three-stretches-of-data/ Published: 2026-10-09 · Series: The road to Bot 7 · Same on three stretches > Ranking 440 buy-and-sell pairs by money on the month they were picked on gives a list of lucky pairs. So we asked a different question: which pair behaves the same — same time in the market, same number of longs and shorts per day, same daily growth — on three stretches of BTC: held-out weeks from training, the validation month, and fourteen days after validation that no step of the selection had touched. Of 440 pairs, 180 traded on all three. The most consistent one, BUY_l3 epoch 3 with SELL_l2 epoch 17, made $1087, $1147 and $1059 on the three stretches. It became the live bot. ## ① Three stretches, one pair at a time The 42 "potentially best" networks were copied out of their training runs and run, unchanged, over three stretches of BTC at 10-minute steps. **Held-out** (08.07 20:30 – 12.08 05:00 UTC, 4,445 steps) is the part of training data on which epochs were chosen. **Validation** (15.08 – 21.09, 5,265 steps) is where windows, thresholds and the networks themselves were chosen. **Test** (21.09 05:10 – 05.10 14:10, 2,001 steps) is data the collector recorded after all that — the networks had never been run on it. Before trusting the new runs, the code was checked against the old ones: on the first 300 test steps, the output of `BUY_pos` epoch 9 matches the exported buy-only bot's own replay exactly, and on held-out the outputs of `BUY_bce` epochs 3 and 17 match the training series to rounding (≤ 5·10⁻⁵). ## ② Consistency, not money, as the score Each pair was run on each stretch with the same rules as before (one trade per 2.3% leg, take 1.9%, stop 2.5%, opposite signal closes). For each stretch four numbers were measured: **share of time in a trade**, **longs per day**, **shorts per day**, and **daily growth** — (money/1000)^(1/days) − 1. For each measure, the spread between its highest and lowest value across the three stretches was divided by that measure's standard deviation over all pairs; the score is the sum of the four spreads. Lower means the pair behaves more alike everywhere. Pairs that do not trade at least one long and one short on every stretch would look perfectly "consistent" with zeros, so they were set aside: **260 of 440**. Of the remaining **180**, the most consistent is `BUY_l3` epoch 3 (window 340 minutes, θ 2.72) with `SELL_l2` epoch 17 (30 minutes, θ 1.74), score **2.29**: in a trade **52% / 46% / 49%** of the time, **0.17 / 0.19 / 0.21** longs and **0.12 / 0.16 / 0.14** shorts per day, daily growth **+0.24% / +0.37% / +0.40%**. ## ③ Against buy & hold on each stretch — and why this pair went live The pair made money on all three stretches. Against simply holding BTC: it beat it on the held-out weeks, when BTC rose only 2.4% (**$1087 vs $1023**); it trailed badly in the validation month, when BTC rose about 29% (**$1147 vs ~$1289**); and on the unseen test it finished level (**$1059 vs $1064**, BTC +6.5%). A bot that is in a trade half the time and shorts some of it cannot keep up with a strong rally; it can earn when the market goes nowhere. That is the profile the selection was looking for — not the richest pair, but the one least likely to change character on new data. On 5 October it was frozen and handed to the live bot: same weights, W 340 / θ 2.72 for buys and W 30 / θ 1.74 for sells, same rules. Fourteen days of test with about five trades is still a thin check. The next article is the overview of bot 7 — training, every stretch, and the list of its real trades so far. ================================================================================ # One Account, Two Networks — 440 Buy-and-Sell Pairs on Validation, and Why the Best Still Trails the Market URL: https://marketflowresear.ch/articles/one-account-two-networks-440-buy-and-sell-pairs-on-validation/ Published: 2026-10-09 · Series: The road to Bot 7 · Buy-and-sell bot > A buy network and a sell network were put on one $1000 account under one set of rules: one trade per 2.3% zigzag leg, take-profit 1.9%, stop 2.5%, and a signal from the other side closes the position. Every one of the 22 "potentially best" buy networks was paired with every one of the 20 sell networks — 440 pairs — and each pair traded the full validation month. 438 of them ended in profit. The best made $1235.78, a gain of 23.6%. Buying and holding BTC over the same month made about 29%. ## ① The rules of a two-sided bot The two networks feed the same account, and every 10 minutes the bot goes through the same order. First, take-profit (**1.9%**) and stop (**2.5%**) are checked against the close — they act immediately, no confirmation. Then the 2.3% zigzag is updated causally, from closes only: a reversal of 2.3% from the current extreme starts a new leg. Then the signals: each side fires when the sum of its probabilities over its own window W reaches its own θ; if both fire at the same step, neither counts. A signal against the current leg starts a new leg of its own side. An open trade is closed by a signal from the other side, at that step's close. A new trade opens only if there is no position and **no trade has been made in the current leg yet** — the bot takes one shot per move, so a long run of signals cannot buy the same move five times. Costs are 0.05% fee plus 0.02% slippage per side, the whole account goes into each trade, no leverage. W and θ of each network are the middle of its 90% zone from the previous step. ## ② 438 of 440 pairs in profit — best $1235.78 **438 of 440 pairs** ended above $1000; the best made **$1235.78** and the worst **$997.41**. The winner pairs `BUY_pos` epoch 15 (window 180 minutes, θ 10.44) with `SELL_pos` epoch 16 (270 minutes, θ 24.84): 10 buys, all closed at take-profit, and **one** sell, also at take-profit. Of 25 zigzag legs, 23 signals were rejected because the leg already had its trade. Second place, `BUY_l2s10` e18 + `SELL_far` e23, made $1225.41 with a busier mix: 12 buys (9 take-profit, 1 stop, 2 closed by signal) and 7 sells (3 / 1 / 3). Look at who wins. The top pairs are mostly buy-driven: their sell networks trade once to seven times a month. In a market that rose all month, the pairs that short least lose least. ## ③ Why "almost all in profit" is not the headline Three things keep this from being a result. First, the benchmark: buying at the first validation step and selling at the last gave about **$1289** — every one of the 440 pairs trails it. A bot that is flat half the time in a strongly rising month is expected to. Second, selection: the networks were chosen on validation, their W and θ were chosen on validation, and the pairs were ranked on validation. The ranking is a list of candidates, not a forecast. Third, sample size: the winning pair made 11 trades. Ten take-profits out of ten buys is what a buy signal looks like in a month that keeps rising. So the useful output of this step is not the $1235.78. It is a working two-sided engine — rules, journal, one trade per leg — and a list of 440 pairs to test on data none of them was chosen on. That test, on held-out training weeks and on unseen days after validation, is the next article, and its winner is a different pair. ================================================================================ # Picking a Network by the Width of Its Good Zone, Not Its Best Point — 42 "Potentially Best" Networks URL: https://marketflowresear.ch/articles/picking-a-network-by-the-width-of-its-good-zone-not-its-best-point/ Published: 2026-10-09 · Series: The road to Bot 7 · Potentially best networks > Every trained network becomes a signal through two knobs: the window W over which its probabilities are summed and the threshold θ that sum must reach. Pick the single best cell of that grid and you usually pick noise. So each of 450 buy candidates and 75 sell candidates was traded on a 72 × 50 grid of W and θ, and for each one we measured how wide the area is where profit stays within 90% of its best. In every loss family the network with the widest such zone was kept — plus, if another epoch earned more than twice as much, that one too. The result: 22 buy and 20 sell networks, all scored on the same validation month. ## ① A grid of 3,600 cells for every network For each candidate, every cell of the grid is a run of one side on its own: the signal fires the moment the sum of probabilities over the last **W minutes** reaches **θ**; the trade is a long for a buy network or a short for a sell network; one trade per 2.3% zigzag leg; take-profit **1.9%**, stop **2.5%**; costs 0.07% per side; $1000 start. W runs **10 to 720 minutes** in 10-minute steps (72 rows), and θ/W — the average probability needed in the window — runs **0.02 to 1.00** in steps of 0.02 (50 columns). The **90% zone** is the largest rectangle around the best cell in which every cell earns at least 90% of the best. Its area, in cells, says how forgiving the network is: a wide zone means a slightly different window or threshold gives nearly the same money; a one-cell zone means the result exists at one point only. The network's working W and θ are taken from the **middle of its zone**, not from the best cell. ## ② Wide and modest, or narrow and rich Within each loss family the network with the **largest 90% zone** is the first pick; ties go to more money. Then the richest network of the same family is checked: if it earns **more than twice** the first pick, it is kept as well and marked as added for money. For buy networks this rule mattered in four families. In `bce`, `pos` and `focal`, epoch 3 earned the same **$30.27** across most or all of the grid — 72, 1,944 and 504 cells — because at that epoch money barely depends on W or θ. The richest epochs of the same families earned **five to seven times more** ($151.32, $211.01, $164.91) but in zones of 1 to 4 cells. In `ladder`, epoch 0 ($119.61) was added over epoch 6 ($27.84). Altogether **450 buy candidates → 22 networks**, **75 sell candidates → 20 networks** (three added for money). `dice` (buy) and `focal` (sell) earn nothing in any cell. ## ③ Sell networks earn less, and the warning that comes with all of this Sells were scored in a month when BTC rose about 29%, so shorting was swimming against the tide: the best sell picks earned **$20–88**, against **$28–211** for buys. Most sell zones are one or two cells wide; the widest, `l3` epoch 4, holds 90% of its money over W 230–290 minutes and 14 cells. Three sell networks were added for money: `l2s1` e0 ($46.84), `l2s2` e9 ($59.83) and `l2s5` e21 ($87.66) — each in a single cell. The width rule is a guard against luck, not a cure for it. Every candidate, every zone and every profit here was measured on the same 38 validation days. A wide zone on validation is a better bet than a sharp peak, but it is still a bet about the future. That is why the next step pairs these networks into one bot and then — the part that matters — checks the pairs on stretches they were not chosen on. ================================================================================ # Teaching the Network to See Tops — Sell Pivots on BTC, One Change and Eighteen Training Runs URL: https://marketflowresear.ch/articles/teaching-the-network-to-see-tops-sell-pivots-on-btc/ Published: 2026-10-09 · Series: The road to Bot 7 · Sell pivots > The bottom-finding network that powers our buy-only bot was rebuilt for the other side of the market with exactly one change: the label is now a 2.3% top zone instead of a bottom zone. Same canvas, same split, same eighteen training runs with different loss functions. Tops turned out to be rarer and harder: on validation only 62 of 5,265 ten-minute steps sit in a top zone. Plain losses reached an F1 of 0.047–0.084 against a base of 0.023; the "ladder" target that accepts a two-hour neighbourhood reached 0.19–0.21 against 0.13. Fine-tuning further did not help, and one loss never fired at all. ## ① One change: the label is a top The study was asked to repeat every step of the bottom work "as precisely as possible, changing one thing". So the canvas — 1,100 records of 100 seconds, 8 order-book features, about 30 hours — is byte-for-byte the input of the bottom network. The split is the same: training 21.02–30.06 (15,878 steps every 10 minutes), a 200-hour gap, held-out 08.07–12.08 (4,445 steps), validation 15.08–21.09 (5,265 steps), all BTC. The label mirrors the bottom label. A **top** is a 2.3% zigzag pivot where at least one of its two legs lasts 7 hours or more; the zone is ±5% of the incoming leg's duration around it, and only where price is within 10% of the leg's move from the top. Training has **66 tops** (279 steps in zone); held-out 6 tops (123 steps); validation **12 tops** (62 steps). That is about one step in eighty-five on validation — a very thin target. ## ② Eighteen runs: plain losses barely see tops, the ladder sees more The networks are trained from scratch with four losses — binary cross-entropy (`bce`), positively weighted (`pos`), `focal` and `dice` — and then fine-tuned from the chosen `bce` epoch with distance-aware losses: `far`, `ladder`, and `ladder2`, which counts a hit anywhere within ±2 hours of the zone, with ten different "silence" weights. The epoch is picked on held-out data by F1 at the best threshold. Among plain losses, `pos` is best both on held-out (F1 0.141, base 0.054) and on validation: average precision 0.056 against a zone frequency of 0.012, AUC **0.787**, F1 **0.084** — 3.7 times the always-yes answer, but it still raises 800 alarms on validation for 62 zone steps. The `ladder2` family reaches F1 **0.187–0.214** on validation with precision 0.15–0.19: about one alarm in six lands within two hours of a top. Those numbers are measured on the wider ±2-hour target, so they are not directly comparable with the plain ones. ## ③ What did not work — and why that matters for the bot The study's own verdict is blunt. The top-ranked run on held-out, `l3`, is its **epoch 0** — the weights it started from (`ladder2 ×10`, epoch 25). Training it further on a ladder of 2 to 37 steps changed nothing. `far` likewise stayed on its starting point. `dice` produced **no signal at all** on held-out or validation. The useful information came from the first two rounds. Tops are harder than bottoms here for a simple reason visible in the data: there are fewer of them that last, and validation, a month in which BTC rose about 29%, had only twelve. A network that is right one time in six still needs a filter before it can trade. That filter is the subject of the next two articles: instead of trusting one threshold, the sell signal becomes a sum of probabilities over a window, and the window and threshold are picked where the result is stable, not where it peaks. ================================================================================ # When a "Fake" Buy Signal Is Really a Deeper Bottom — Rule 7.1, Tested on Validation and Unseen Days URL: https://marketflowresear.ch/articles/when-a-fake-buy-signal-is-really-a-deeper-bottom-rule-7-1/ Published: 2026-10-09 · Series: The road to Bot 7 · Rule 7.1 > Our buy-only bot throws away a buy signal if price has not risen 2.3% since the previous signal — a repeat call inside the same dip is treated as fake. On the nine unseen days after validation that filter rejected 36 signals and left one trade. Rule 7.1 asks one more question before rejecting: did price, between the last peak and now, make a lower bottom within 1% of the current price? If so, the signal is real, and the take-profit is measured from that lower bottom. With the rule, fakes on unseen days fell from 36 to 0, trades rose from 1 to 3, and the result from $1008.45 to $1034.12. ## ① Rule 7: why the bot ignores repeat signals The network marks bottoms, and a bottom is a place, not a moment: the signal keeps firing for hours while price grinds along the lows. After a trade closes, the next signal in the same dip would buy the same bottom twice. So rule 7: once the bot has a closed trade and no position, a signal is **ignored if the highest close between the previous signal and this one is less than 2.3% above the current price**. Price has to have left the area and come back before the bot buys again. That works when a dip is one dip. It fails when the market makes a staircase down: a peak, a drop of more than 2.3%, a bottom, a small bounce — and a new signal a little above that bottom. Rule 7 measures from the wrong point and calls it fake. ## ② Rule 7.1: a lower bottom within 1% The rule is checked only for a signal that rule 7 has already called fake, so it can only add trades, never remove them. Three points are found on the 100-second records between the previous signal and the current one: the **peak** — the highest close; the **bottom** — the lowest close after that peak; and the **current price** — the close at the signal. If the peak is more than **2.3% above the bottom**, the bottom is **below the current price**, and the current price is **less than 1% above the bottom**, the trade opens. Entry and stop are as usual (stop 2% below entry); the take-profit base is the bottom itself, or a lower price if one comes after entry: take = min(bottom, lowest price after entry) × 1.02. The idea comes from how a trader would read the chart — "the market already made its low a few hours ago, we are still near it" — and the target is smaller because the move has partly started. ## ③ Results: one more trade on validation, two more on unseen days On validation (15.08–21.09) the rule turned one rejected signal into a trade: in at 78,863.46 on 7 September, bottom 78,713.21, out at take-profit on 9 September at 79,273.84, **+0.38%**. Trades went from 8 to 9, rejections from 32 to 15, money from **$1103.17 to $1107.36**. On the unseen days (21.09–30.09) the effect was bigger: both the 25 and 29 September entries came through rule 7.1, at 83,811.35 above a bottom of 83,261.89 and at 83,258.01 above a bottom of 82,621.70. Trades went from 1 to 3, rejections from 36 to 0, money from **$1008.45 to $1034.12**. No trade in any run hit the stop. The bot ships with a take-profit of **1.9%** rather than 2%: same entries, earlier exits — $1100.85 on validation and $1032.92 on unseen days. Two cautions. The rule was written after looking at validation charts, so validation is not a fair test of it; the unseen days are, and there it added two trades out of two. And three trades are not a sample — the honest summary is "it did what it was designed to do, twice". ================================================================================ # A Buy-Only Bot on Nine Days It Never Saw — Three Take-Profits and a Draw With Buy & Hold URL: https://marketflowresear.ch/articles/a-buy-only-bot-on-nine-days-it-never-saw/ Published: 2026-10-09 · Series: The road to Bot 7 · Bot 7.0 on unseen days > The buy-only bot from the previous study had one weakness we wrote down plainly: its window, threshold and stop were chosen on the same 38 validation days it was then scored on. So we froze it and let it walk through the days the data collector recorded after validation ended — 21 to 30 September 2026, nine days nobody had looked at. It opened three trades and closed all three at take-profit, no stop-outs: $1000 became $1032.92. Buying and holding over the same steps gave $1035.51. A clean run, and a draw with the market. ## ① The frozen bot and the days it never saw Nothing was retrained or re-tuned. The bot is the one exported from the study: the `BUY_pos` network at epoch 9 reads a canvas of **1,100 records of 100 seconds** (about 30 hours of order book and price, 8 features) every 10 minutes and gives the probability that this moment is inside a 2.3% bottom zone. The signal is the **sum of those probabilities over the last 18 steps (180 minutes)**; the bot buys when the sum reaches **11.74**. Take-profit sits **1.9% above the lowest price after entry** — if price keeps falling after the buy, the target walks down with it — and the stop is **2% below entry**. The test stretch starts the step after the last validation step: **21.09 05:00 to 30.09 16:10 UTC**. The model never trained on it, and the window, threshold and stop were never chosen on it. The collector had gaps — 68 of 1,364 steps have no 100-second record ending at them, the longest a 54-step hole overnight on 28–29 September — and the bot simply skips those, exactly as it did on validation. Price went from 81,400 at the first step to a high of 87,278 on 21 September and ended at 84,385. ## ② Three entries, three take-profits The signal fired on 41 steps, in three clusters: 23 September afternoon, 25 September afternoon and evening, 29 September afternoon. The first step of each cluster opened a trade; the rest of the cluster only confirmed the position. **23 Sep 16:40**, bought at 84,027.71, closed at take-profit on 24 Sep 14:28 at 84,856.60 — **+0.85%**. **25 Sep 14:50**, bought at 83,811.35, closed on 27 Sep 08:16 at 84,844.01 — **+1.09%**. **29 Sep 16:30**, bought at 83,258.01, closed on 30 Sep 12:31 at 84,476.79 — **+1.32%**. Costs are inside these numbers: 0.05% fee and 0.02% slippage per side. Two of the three entries exist only because of a rule added after validation (rule 7.1, the next article): the old fake-signal filter would have thrown both clusters away, and the bot would have made one trade and $1008.45 in nine days. ## ③ $1032.92 against $1035.51 — what a draw tells us On validation, where the parameters were picked, the bot ended at **$1100.85** against **$1289.36** for buy and hold over the same steps: nine trades, nine take-profits, and still far behind a market that rose 29%. On the nine unseen days it ended at **$1032.92** against **$1035.51**. The gap closed — not because the bot got better, but because the market rose less. What the run does show: the signal did not fall apart outside the days it was tuned on. Every entry was followed by a rise of at least 1.9% from the lowest price after the buy, and no trade hit the stop. The bot was out of the market most of the time and still matched holding. What it does not show: three trades over nine days is far too few to call a win rate. A fair coin gives three heads in a row one time in eight. This is a check that nothing broke, not proof of an edge. The next tests in this series move the same idea to both sides of the market and to live data. ================================================================================ # From a Canvas of the Whole Leg to a Buy-Only Bot — What Survived, and What It Earned URL: https://marketflowresear.ch/articles/from-a-canvas-of-the-leg-to-a-buy-only-bot-what-survived/ Published: 2026-09-30 · Series: The road to Bot 7 · Canvas and the buy bot > The last study of the series put a whole leg — and 50 rows on either side — onto one canvas and asked a network to mark pivots and corrections on it. On labelled windows it hit 38% of pivot zones; run live over the series, 5% of its pivot calls landed. A longer canvas, 160 hours on 100-second records, and windows of uniform length lifted precision to about 30%. Its best trick: 29% of pivots flagged a median 2.4 hours before the zigzag confirms them. The result became a paper-trading buy-only bot for BTC. On 38 days of validation it made +10.3% with eight trades and no stop-outs — while buying and holding made +36.6%, and its parameters were tuned on those same days. ## ① A canvas of the leg, and the signature it carries The task was set in one sentence: data comes in, becomes a canvas, and the model says whether the canvas holds a 2.3% pivot zone — the start or the end of a leg, which are the same thing — and marks the corrections inside the leg as local. Every leg longer than 7 hours is laid onto **500 rows**, with **50 rows** added on each side, on the 30-second standard of the previous study: 600 × 7 features of `210×10-1×7d/d`. Six coins, 1,210 legs and 9,068 windows for training, 352 legs and 2,250 windows for validation. Before training, the labels were **refined**: inside each labelled zone only the rows that actually carry the signal are kept. A grid chose the variant best correlated with the targets — all 7 features, a 3-row window, the peak within ±2 rows of the pivot, absolute values, a 0.7 quantile. The signal is present in 76% of start zones, 75% of end zones and 64% of correction zones, against 51–58% in controls. The signature is stable: pivot windows from *different* legs correlate at **0.45–0.49**, and negatively with the body of a leg (−0.18 to −0.19), on validation too. Start and end are one signal (0.468). A correction is a weaker version of it (0.28–0.29 with pivots). Resistance- and support-per-flow features are weakest next to a pivot, stronger in a correction, strongest in the body; flow-per-level goes the opposite way. And a leg's own start and end are no more alike than a start and an end of *different* legs — the pivot signature is shared by all legs. ## ② 38% on windows, 5% live — and how the canvas grew The first three-class network (pivot / correction / body) found **38%** of pivot zones on validation windows, and 38% of its pivot calls landed in a pivot zone; corrections were harder (F1 0.24). Validation held at the level of held-out training legs — no overfitting. Then it was run the way it would be used: sliding windows over the unlabelled validation series. Pivot-call precision fell to **4–7%**, recall 15–29%. A labelled window already tells the network there is a leg in it; the live series does not. Several rounds followed. Clustering the refined signals split them into "movement without levels" and "levels without movement". A longer canvas — **1,100 rows on 100-second records, 160 hours** — found 41% of pivot zones on validation with 15% precision, four times random. Three output heads (top, correction, bottom) with a cycle of training windows reached F1 about 0.21 — six to eight times random, but five or six false calls per good one. Training on random windows with 1–8 pivots helped slightly. Training on **windows of uniform length** was the strongest step: top 0.224 → **0.330**, bottom 0.209 → **0.279**, and precision of the pivot heads rose for the first time to about **0.30** — two false calls per good one instead of five. The best window length on validation was 6–7 days. The correction head stayed at 0.15–0.17 in every run. Trading a flip strategy on the pivot-zone head over the validation month beat holding on no coin (three up, three down, the worst trades being shorts against a rising market). ## ③ Before the zigzag: 81 of 284 pivots, 2.4 hours early A zigzag confirms a 2.3% pivot only after price has moved 2.3% away. The next head answered a live question at every moment T: **is T inside a 2.3% pivot zone?** Inputs were checked for leaks: the side-of-leg channel computed live on data cut at T matches the finished series on every event before T. On six coins of validation (window 300 hours, a call every 10 minutes): **81 of 284 pivots (28.5%)** were flagged before the zigzag, a median **2.4 hours** earlier, when price had retraced 1.6% of the 2.3%. Random signals at the same rate: 15 of 284. Precision of fresh signals **40%** (random 20%), 0.76 signals per coin per day, F1 0.333. The previous model without this training was close (0.314), so the gain over it is small. Held-out training legs gave 0.569 — but they took part in choosing epoch, threshold and window, and validation was a different market (a month of growth on all coins); validation is the honest number. XRP, with the most short legs, was weakest (8 of 84). ## ④ The buy-only bot: bottoms only, BTC only — and honest about its test The last stage narrowed everything to what can be traded simply: **BTC, buying only, bottoms only.** A transformer on the 1,100 × 8 canvas (160 hours up to T, the eighth channel is the probability of the "levels without movement" cluster) outputs P(T is in the bottom zone of a 2.3% leg of at least 7 hours). The buy signal is the **sum of P over the last 180 minutes** ≥ 11.74 (the 0.97 quantile of that sum). Take-profit 2% above the lowest price since entry, stop-loss 2% below entry, a signal after a closed trade without a 2.3% rise in between is treated as fake. Costs: 0.05% fee plus 0.02% slippage per side. On validation (15 August – 21 September, twelve 2.3% up legs): **8 trades, all closed by take-profit, no stops, $1,000 → $1,103.17** — 12.2% of what a perfect catcher of every up leg would make ($2,140), and **below buy-and-hold** ($1,366). The loss functions tried on the way mostly failed on validation (BCE: AUC 0.657, precision 2% on a 0.7% base); what worked was a wider target (bottom zone ± 2 hours), a penalty for silence, and summing over time. The honest caveat is written into the bot's own file: model, threshold and trade parameters were **chosen and measured on the same 12 validation legs** — there is no separate segment that confirms them. So this is the series' first complete trading candidate, not a proven strategy. It runs in paper mode only, sends no orders, and its full description — how to rebuild it from raw collector data, every parameter and the checksum of the model — is attached below. ================================================================================ # How Full Is This Leg? A Network That Finally Beats the Counter — by Reading Its Last Rows URL: https://marketflowresear.ch/articles/how-full-is-this-leg-a-network-that-finally-beats-the-counter/ Published: 2026-09-30 · Series: The road to Bot 7 · Leg fullness > Give a network the unfinished leg — everything from the last confirmed pivot to now, as one fixed-size canvas — and ask how complete it is. For the first time in this series a model beats the simple counter of events since the pivot on unseen weeks: fullness AUC 0.77 against 0.70, error 0.18 against 0.24. The surprise is where the knowledge comes from: the last 16 rows of the canvas do as well as all 500. On a 30-second standard with sliding windows the gap widens (0.78 vs 0.62), and the network locates a pivot inside its window with AUC 0.96. What it still cannot do cleanly is call "the leg is over" live: nine of ten such signals miss. ## ① The edge of a correction looks like the edge of a leg Study 26 tried to estimate how much of its leg an event has travelled and could not beat the constant 0.5; a counter of events since the confirmed pivot was the bar nobody cleared. This study changes the input. The network gets the **unfinished leg itself** — every event from the confirmed pivot to now — and says how full it is: 0 at the start, 1 at the end. Six coins, `210×10-1×7d/d`, split by date (603 legs train, 106 validation). The first stage mapped the roles of events inside a leg: its start, its end, and both edges of every internal correction. Leg edges stand out from the body clearly (AUC 0.72–0.81, the same sign on all coins and on validation). The edges of corrections carry **the same signature, weaker** — the difference between a reversal edge and a correction edge is only 0.07–0.11 of AUC. So fullness cannot come from one event; it has to come from the sequence: how many such edges there were and how much move lies between them. The number of corrections behind is causally known and travels with fullness. ## ② A canvas of the whole leg — and the last rows carry it Legs range from tens to thousands of events, so the prefix is laid onto a **fixed canvas**: the class is recomputed from second-by-second data at whatever step makes the prefix fit 500 rows × 9 blocks × 7 features — a long leg is compressed, a short one stretched. On unseen weeks the network beats the counter, and the bootstrap over legs does not cover zero: fullness AUC **0.768** vs 0.699, share error **0.184** vs 0.237 (the constant: 0.271). But a control network that sees only the **last 16 rows** of the canvas — the last 3.2% of the prefix — does the same or better (0.784, 0.183); every difference between them covers zero. What the network knows about fullness it reads from the *end* of the prefix. The shape of the whole leg adds nothing. And the hardest case stays hard: a prefix cut at the edge of a correction gives 0.67, against 0.80–0.83 at random points. A second setup moved to a 30-second standard with sliding windows that may run into the next leg, with outputs as a staircase of thresholds. Here the full canvas **does** beat its tail by 0.10 (0.781 vs 0.682): a window that crosses into the next leg carries the pivot inside the canvas, and only the whole canvas shows it. The network beats the counter on every threshold and every coin; the gap is widest where the counter is helpless — windows that overshot the leg (0.79–0.83 vs 0.54–0.58). It also finds *which row* of the canvas holds the pivot with AUC **0.960** (counter 0.639). The weakest point is the boundary itself: 0.714 at 98% full, 0.752 at "100% or more". ## ③ No architecture beats the compressed canvas — and live calls still miss The next round removed the compression: the canvas fed whole, 500 rows, to attention with no stride; to LSTMs and transformers as a sequence; to an MLP on 4,000 inputs; to MLP-Mixers. **Compression loses nothing.** Uncompressed attention is not better (0.765 vs 0.781), the big MLP overfits from its first epoch, the best LSTM and transformer reach 0.764–0.766, and a deeper transformer (8 heads × 4 layers) is worse on validation (0.739). A Mixer on a *more* compressed 50 × 8 canvas draws level with the chosen model (0.789 vs 0.781, one run, one seed). An input mask for dead rows is unnecessary — the network sees seven zeros anyway. The last stage asked for pivots directly: a zone "the leg is over" (95–105% of its duration, within 10% of its price range), marked on every row. On validation windows precision is **0.14–0.16**, three times the 0.055 of a random row, with recall 0.20–0.38. Run live over the unlabelled series, precision drops to **0.08–0.10**: 3–10 times more signals than pivots, nine of ten outside the zone. A 12-point grid of penalties for misses and false rows moved only the height of the output (99th percentile from 0.12 to 0.94) — precision stayed at 0.14–0.16 in every variant. The weights change how loud the network is, not how well it separates. That is where the final study of this series starts: a longer canvas around the leg, and the pivots themselves as the target. ================================================================================ # Where a Leg Really Ends — Four Events Earlier Than the Zigzag Says URL: https://marketflowresear.ch/articles/where-a-leg-really-ends-four-events-earlier-than-the-zigzag-says/ Published: 2026-09-30 · Series: The road to Bot 7 · Where a leg ends > We went looking for a unique, universal signature of a pivot in 531 legs of six coins. The book turned out to be a mirror — tops and bottoms read with one ruler once buyer and seller features swap. The zigzag's pivot turned out to sit in the wrong place: the true boundary of a leg is the extreme of the closing price within ±25 events, four events earlier, and there the signature becomes symmetric and one event sharp. What we did not find is uniqueness: a 0.5% correction carries the same signature, weaker. The signature measures the strength of a turn — not whether the leg is over. ## ① A mirror, and a boundary in the wrong place The goal was a pivot signature that is both **unique** — present only at leg boundaries — and **universal** — the same for rises and falls. The class is `210×10-1×7d/d`, whose features come in buyer/seller pairs, measured over **531 whole legs** of six coins with 465 continuous joints. First, the mirror. If the series is mirror-symmetric, the signature of a top must equal the signature of a bottom with the pairs swapped. It does, to within 0.02–0.05 of rank against an effect of 0.15–0.25; tops are louder than bottoms by the same small margin. So all 531 legs can be measured with one ruler. Second, *where* the boundary is. The zigzag's pivot sits on an EMA-10 of the opening price, and an EMA lags. Four anchors were tried. At the raw EMA pivot the signature is 0.366, peaks four events *before* the pivot, and its profile is lopsided (left/right 3.10). Anchored on the **extreme of the closing price within ±25 events**, it becomes **0.589**, peaks exactly at the point, and turns symmetric (1.05). That boundary lies a median **4 events** before the EMA pivot in 99% of legs (3–5.5 by coin), adds 0.17% to each leg's range, and puts the boundary in the top 10% of its own leg's events in 52% of legs, against 26% for the EMA pivot. This became the project's labelling standard: every zigzag, any threshold, is built on EMA-10 and then **snapped to the close extreme within ±25 events**. ## ② One event, and the last push is your own side The user's hypothesis was that at the end of a rise, sellers overpower buyers, and the leg's end should be set so that this final burst lies inside it. The data confirm it with the order reversed. At the boundary the loudest side is the leg's **own** — the last push of buyers at a top (0.849), of sellers at a bottom (0.830). The opposing side overtakes it on the **next event** (+1), the same way up and down. So the end of a leg is the final burst of its own side, and the first event of the opposing side already belongs to the next leg — exactly what the close anchor produces. A reversal is **one event**, not a zone: the signature is 0.619 at the point and 0.409 two events away. The ±15-event zones of earlier studies were the blur of the old labelling. Direction the class takes mostly from price: beyond the event's own price move, the book adds +0.036 of rank (t +3.9) and nothing on ETH or SOL. ## ③ Not unique: a correction is a smaller boundary Third, uniqueness — and here the answer is no. A **0.5% correction** carries the same signature, weaker: boundary 0.589, correction 0.353, leg body −0.033; boundary against correction AUC **0.664**. The signature grows with the size of the turn — from 0.245 in the smallest quintile to **0.533** in the largest (Spearman +0.236). It reads as **turn strength**, not "the leg is over". The mechanism of a correction is the same — own volume peaks, levels collapse, the other side overtakes at +1. The difference lives in the surroundings, not the burst (AUC 0.670 vs 0.509), and with turn size matched it disappears (91 pairs, difference −0.009, t −0.2). The last 10 events *before* the point separate them best (0.674), without any event of the next leg. A final measurement asked, on 9,300 edge events: does this event belong to the ending leg or the new one? With the close anchor: **0.768** by date, **0.811** on a held-out coin. Price reads it; the class adds 0.008. But the anchor matters for the class: 0.586 → 0.721 when the boundary moves to the close extreme — the most direct measure of the new standard's value. And the earlier 0.877 of study 28 was inflated by the late pivot; on the exact boundary it is 0.768. The measurement is conditional: the model is asked only on edge events, and finding the edge in the live series is a separate, poorly solved problem. A strong second link does not rescue a weak first one. The next study stops asking "is the leg over" and asks the network to see the whole leg at once. ================================================================================ # Can Our Networks' Outputs Become a Buy/Sell Signal? A Simple 1.2% Zigzag Says No URL: https://marketflowresear.ch/articles/can-the-networks-outputs-become-a-buy-sell-signal-a-simple-zigzag-says-no/ Published: 2026-09-30 · Series: The road to Bot 7 · Buy / sell from networks > Our networks each say something about a leg: it is ending, it is 80% done, this is a reversal zone. None says "buy" or "sell". So we combined their outputs into one decision and raced it against three rivals: each channel alone, a coin with the same number of signals, and a causal 1.2% zigzag on the same price. The combination found 40% of reversals within ±50 events — where chance at that frequency finds 30%. The plain zigzag found 72%. With $1,000 on BTC, the networks ended level with the coin; the zigzag ended next to buy-and-hold. What the networks do know is where a reversal was. ## ① The race: combiner vs chance vs a simple rule The inputs are the outputs of the approved networks laid on one timeline per coin: `legtooth` and `legline` (where in the leg), `hazard100` and `hazard4` (a pivot soon), and the pivot and correction zones. Six coins, 412,811 events, 718 reversals of the 2.3% zigzag on EMA-10 (607 train, 111 later). The target zone is asymmetric — **50 events before a reversal and 15 after** — because an early signal can still be traded, a late one cannot. Three rivals stand next to the combiner, so that "it adds nothing" shows up as a number. On the unseen weeks (60 reversals): an MLP combiner of the network outputs gives 151 signals and catches **40.0%** within ±50 events. That looks decent until the chance curve is drawn — a coin with 151 signals catches **30.3%** on average over 20 draws. So the combiner is ×1.3 chance. On price features alone it is worse (15%), both together worse still (28%). A causal **1.2% zigzag** on the same price — no model at all — catches **71.7%** with 136 signals and is the only rule that gains on the move (+1.20% of the series' move, the combiner −0.99%). The chance curve is compulsory reading for every table in this study: 40% at 151 signals and 40% at 60 signals are very different results (chance: 30.3% and 12.3%). ## ② Why the combiner has nothing to combine The breakdown of the channels explains the failure. None of them carries direction (AUC 0.33–0.47 for up versus down). They duplicate each other (Spearman up to 1.00). And their level drifts between train and validation. A classifier of events has nothing to build a decision from that its input does not contain. Memory helped somewhat: a GRU along the event sequence on 11 instantaneous numbers keeps ×2.2–2.4 over chance where the combiner keeps ×1.3–1.7, and catches 46.7% within ±50 on 93 signals. Its move is still negative (−2.86%), and its learning curve stays flat for 20 epochs — the bottleneck is not the architecture. LSTM versus GRU is within noise (8 pivots swap their order). Defining the reversal zone as a share of the leg (last 10% + 15 events) instead of a fixed window pulled signals closer to reversals — lift over chance from ×2.2 to ×5.9 — but the captured move stayed negative. The rival's threshold was not picked by eye: a ladder from 0.4% to 3.0% puts **1.2%** on top by its advantage over a same-frequency coin (**×10.5** within ±15 events). Lower thresholds sit closer to the pivot but capture little of the move; 2.3% fires exactly once per reversal but 96.5 events late. ## ③ $1,000 on BTC: nothing beats holding Hits within ±50 events are not money. The last test asks directly: what would $1,000 have become on the unseen BTC window — 3,549 events, 13.3 days, price 63,043 → 77,404, an uptrend with six 2.3% reversals? Fully invested, no leverage, compounding; entry on the event **after** the signal; costs of 0.05% taker fee plus 0.02% slippage per side; drawdown marked on every event. There is no stop-loss, so this measures the signal, not a strategy — and the window is small. **Nothing beat buy-and-hold: $1,226.33.** Long-only, the 1.2% zigzag ends at **$1,208.83** with a drawdown of 4.60% against 5.21% for holding — slightly better Sharpe at nearly the same result. That is the only edge in the study. The two network combiners end at $1,032 and $1,046; the coin at $1,046. Allowing shorts makes the combiners worse than the coin ($981 and $849 vs $882). With zero costs the ranking stays: it is the signals, not the fees. A one-trade-per-leg rule on the direction head, tuned on a held-out segment and run on all six coins, earned +6.23% on validation — against +19.38% for an EMA crossover of price itself tuned by the same grid, +24.26% for holding, and **+7.48% for a coin** of the same frequency. The direction head adds nothing to price that converts into money. ## ④ What the networks do know: where it happened The networks turned out useful for a different question than the one they were asked. They do not say when to reverse — but they say **where the reversal was**. A zigzag is late by construction: it waits for price to move away from the extreme. Run the pivot network over the window behind a zigzag signal and it moves the named point closer: the median offset falls from **47 to 20.2 events**, and memory strength lifts hits within ±5 events from **6.7% to 26.7%**. This is hindsight — no future is in the window — but the point of action lies in the past, and it matters: the entry could be referred back to a better level. A later chain tested exactly this: candidates from crossings of the head with an EMA, then the networks naming the event. As a *filter* they cannot work — trained only on true edges, they have no class for "nothing here" and say "here it is" in 80–86% of zones, random or not. As a *pointer* they do work: when a boundary is in the zone, they name it with a median error of **4 events**, finding 6 of the 7 reachable ones where a random event of the same zone finds 2.5. The numbers stand on 60 validation reversals, 24 of them on XRP. The order of magnitude is visible; differences of a few points between neighbouring rows are noise. ================================================================================ # A Loss Ladder for Five Trained Networks — and the Biggest Win That Was a Dropout Bug URL: https://marketflowresear.ch/articles/a-loss-ladder-for-five-trained-networks-and-the-win-that-was-a-dropout-bug/ Published: 2026-09-30 · Series: The road to Bot 7 · Loss ladder > We took five approved networks from this series and tried to improve them without retraining: change the loss function between epochs, raise the penalty step by step, keep an epoch only if a fixed metric on validation improves. 124 attempts, 6.9 machine hours. One network truly improved — the one whose own training had stopped too early — and it improved from a smaller learning rate, not a new loss. The spectacular result, +0.47 on the zone model, vanished when the saved weights were measured again in a separate process: the GPU backend had left dropout switched on during evaluation. ## ① The ladder and its fixed yardstick This series has several approved networks, each with its best version: weights, settings and the validation number it was chosen by. The question here: **can an approved version be fine-tuned by changing the loss function between epochs** so that its own fixed metric gets better? And a service question: were they all trained to the end, or did some stop because the epoch budget ran out? The ladder starts from the approved weights. Each rung is one epoch under its own loss, with the penalty growing rung by rung; after the epoch, the fixed metric is measured on validation. Better — keep the weights and continue from them. Worse — roll back. The metric is chosen in advance and does not depend on the penalty. And every model gets a **measurement noise** — the spread of repeated measurements of the same point — so a change can be read against it. Five networks: `legleft` (how many events to the end of the leg), `legtip` (end-of-leg signal), `hazard100` (a pivot within the next 100 events), `hazard4` (four horizons), and `zone` (pivot zone, correction zone, ordinary event). 124 rung attempts in total. ## ② Fine-tuning helps exactly where training stopped short The result sorts cleanly by one property — **how each network's own training had ended**. `hazard100` had been stopped by patience while its metric was still rising (best epoch 8 of 11); the ladder added **+0.0224** (0.7204 → 0.7428), with 14 of 29 attempts outside the noise. `legleft` and `legtip` had trained to the end: 0 of 23 and 0 of 25. `hazard4` had also been stopped by patience, but none of its 22 attempts moved the metric even by the noise (±0.0026) — what matters is whether the metric was still moving, not how many epochs were allowed. The rungs `hazard100` kept were "the same loss, learning rate ×0.3" and "gradient window 40". No new loss shape — focal, proximity-to-pivot weighting, tripled label weight — gave anything a smaller step on the old loss did not. The rule for the rest of the project: **before inventing a loss, finish training on a smaller step.** Two more lessons. For `legleft`, all 23 attempts landed at 0.85–0.90 against the approved 0.8373 — the approved number was the best of 32 epochs selected on the same validation, and one new epoch simply returns the model to its typical level. And `hazard100`'s gain is mostly on its weakest coin: BNB from 0.555 to 0.639, while the two strongest coins slipped slightly. "The model improved" really means "the worst part improved". ## ③ The +0.47 that was not there The headline number of the run was `zone`: score 0.7055 → **1.1799**, and the confusion between the pivot and correction channels cut from 0.417 to 0.263 — five rungs kept, the training curves spotless. Then all saved weights were measured again, event by event on validation, in a separate process. Four networks reproduced their numbers exactly. `zone` did not: approved **1.0471**, ladder **0.9909** — worse by 0.056, with the confusion *up* from 0.400 to 0.462. The cause: after a backward pass, the `mps` accelerator kept `nn.Dropout` active during evaluation even in `eval` mode. The approved version lost more to that noise than the version trained under the targeted penalty — hence the entire "gain". The ladder version also never says "zone" in argmax mode: its accuracy 0.8936 equals the share of the majority class. The rule that comes out of it reaches beyond this study: **any number measured in the same process as training on `mps` must be re-measured in a separate CPU run.** Measuring saved weights costs minutes and catches what no training curve can. Two further checks close the study. Replacing the zigzag's pivots with fake ones every 150 events barely moved `legleft` (narrow corridor 9.9% → 11.1%); its output does not follow a step counter (correlation 0.036) — it answers from the class, and the labels mostly give it a window of **silence**. And letting a network reset its own leg — no zigzag at all — reached the same corridor as the labelled version, paying with coverage: a monotone shape can be built into the architecture (`s = (1 − r)·min(s + g, 1)`), but the *place* of the reversal stays a question of data. On the right reset rate the detector hits 11–17% of reversals, with 88% of its signals false. ================================================================================ # A Correction and a Reversal Are One Event of Different Strength — What the Book Shows Inside a Leg URL: https://marketflowresear.ch/articles/correction-and-reversal-are-one-event-of-different-strength/ Published: 2026-09-30 · Series: The road to Bot 7 · One axis: normal → correction → pivot > Every leg of a zigzag holds its own common level in the order book, and removing it would make the unusual events stand out — if only it could be known in time. It cannot: the previous leg predicts it so poorly that subtracting it adds noise. What the book does show is a reversal zone of about 15 events with a clear signature — and the same signature, weaker, inside every correction. Normal event, correction, pivot: one axis. Models find the pivot zone at AUC 0.72–0.75 and put 8.5× the base rate in their most confident answers, but no memory, loss or penalty separates a pivot from a correction without breaking the correction channel. ## ① A common level — known only after the leg ends Inside one leg the seven features of `210×10-1×7d/d` sit at a level different from the neighbouring leg's. That level is the same for every event of the leg, so it says nothing about any single event — it only hides the ones that stand out. The idea: subtract it and look at what is left. Two conditions: up and down legs measured separately (different regimes), and the subtracted base must be **causal**. A leg's own average knows everything that happened in it, so the base comes from the **previous leg of the same direction**, which ended before this one began. BTC, 70,647 events. The common level is real: subtracting the leg's own mean removes **up to 14%** of the spread — support per unit of selling drops from 0.294 to 0.258 on up legs, resistance per unit of buying from 0.302 to 0.263. It is mostly the book levels; balances and price carry 1–6%. It carries over the pivot only halfway (0.45–0.51 on up legs, 0.18–0.37 on down legs, zero in rank on some features). So the causal base **adds** spread instead of removing it: 0.294 → 0.303 on up legs, 0.282 → 0.294 on down legs. Subtracting a level you did not guess adds the guess's own error. Inside a leg the level drifts — neighbouring 5%-slices correlate at 0.53–0.82, the first and last slice at 0.02–0.22 — and the position repeats in the next leg of the same direction only weakly (0.22–0.30 up, near control down), more like a market regime than a memory. Six book features know nothing about the direction of the *neighbouring* leg (AUC 0.49–0.52, exactly the control); only the price derivative does (0.533), at the leg's edges. ## ② Normal, correction, pivot — one axis Next, the zones themselves. A reversal zone is about **15 events** (5.8 before, the pivot, 7.3 after) — some 53 minutes in which price moves 0.71%. A correction zone is shorter (11.4 events) and narrower (0.42%). The reversal has a signature in the class, and it is not an artefact of how zones are cut. Resistance per unit of buying rises from 0.484 to **0.716** in rank; flow per resistance falls from 0.512 to **0.336**. A fixed-window control gives the same (AUC 0.696 for the first, 0.338 for the second). The price derivative takes no part at all (0.499). And a correction is **the same signature, weaker**. In the fixed-window control, correction against a normal event gives 0.611; pivot against a normal event, 0.696; pivot against correction, 0.597. The three kinds do not occupy different places — they sit **on one axis**: normal → correction → pivot. The event-level dissimilarity itself is small (+9.7% at the pivot, +1.8% at a correction), so any zone threshold must be relative to the leg, not fixed. ## ③ Models find the zone — not the difference A three-class model (normal / correction zone / pivot zone), trained on six coins because BTC alone has only eight pivot zones in validation, reaches AUC **0.724** for the pivot zone with a **causal** window — slightly better than a centred one (0.718): everything it knows about a reversal, it knows from the past. Its most confident 0.1% of events contain **17.4%** pivot-zone events against 2.1% base — **×8.5**; at the top 1%, 7.9% (×3.9). By coin it ranges from 0.625 (XRP) to 0.750 (ETH), and BTC's top 1% contains only corrections. A memory network over one, three, five legs or the whole series adds a little (pivot zone **0.737–0.741**, top 1% ×4.3) and nothing across memory lengths. An early version seemed to gain from longer memory (0.823) — that was the block boundaries coinciding with pivots, the network reading the way the data was sliced. Changing the output from softmax to independent channels helped the rare correction channel more than any memory (0.634 → 0.700). The obstacle is not "reversal versus market" — normal events and corrections are well separated (AUC 0.869 and 0.816 on BTC) — but **reversal versus correction**. A penalty aimed exactly at that confusion drove it from 0.356 to 0.010 — and pushed the correction channel's AUC to 0.469, below chance. Every weight and loss with the penalty did the same; the widest network gave the best raw numbers (0.753 pivot, 0.717 correction). The data agree with stage 4: a correction and a pivot are not different events but one event of different strength, and the book at the moment cannot say how strong this one will turn out. ================================================================================ # The Book Sees the Edge of a Leg, Not Its End — Event by Event on BTC URL: https://marketflowresear.ch/articles/the-book-sees-the-edge-of-a-leg-not-its-end/ Published: 2026-09-30 · Series: The road to Bot 7 · Edge, not end > Event by event on BTC, every feature of our order-book class carries its place in the leg: a U-shaped profile that holds inside individual legs, with the same sign in 80% of them. But what it reads is the distance to a pivot, not the progress through the leg. It tells a real end of a leg from a shallow 0.5% correction (AUC 0.669), and loses that ability as the correction deepens — at 1.5% there is nothing. A detector of "this is the tail of a leg" lifts precision up to ×19 over the base, yet cannot tell a tail from a head. The book knows it is at an edge; it does not know which one. ## ① Place in the leg is written in every feature Study 29 measured the class along the leg with one summary per event. This one goes event by event on BTC (70,647 events, 70 legs of the 2.3% zigzag on EMA-10) and summarises each event six ways — mean, first and last block, peak, spread, slope — in ranks. The profile is U-shaped **for all seven features and all six summaries**. Flow-per-level ratios and the price derivative are higher at the edges; level-per-flow ratios are lower, and lowest in the last tenth (0.329 for resistance per unit of buying, against 0.47–0.48 mid-leg). It is one statement read from both sides of the ratio: at the edge of a leg the flow side is thick relative to the level side, in the middle the other way round. The strongest summaries are not the mean but the **spread** and the **peak** inside the event. Up and down legs show it with the same sign. The effect is not an artefact of pooling legs from different regimes: measured *inside each leg separately*, edge against middle holds (AUC 0.36–0.61, t up to 7.2) with the same sign in 80% of legs. But there is no monotonic walk from one pivot to the next — Spearman with position never exceeds 0.04. The class reads **distance to a pivot**, not the share of the leg travelled. And the direction of a single event's own move is invisible to it: only the price derivative separates events moving with the leg from events moving against it (t +6.5); for the rest of the class |t| < 4. ## ② A real end vs a correction: only when the correction is small Knowing the pivot afterwards is easy; the causal question is harder. Inside every leg there are places where price turned against it and the leg went on. Is the true end different from such a **correction** — a pivot of a nested smaller zigzag, at least 40 events from the leg's ends? With 1,512 combinations tried (42 measures × 3 curves × 4 windows × 3 metrics), a |z| near 3 appears by itself, so every result is compared with the largest |z| of the whole search after shuffling the pivot/correction label 500 times. Against 0.8–1.5% corrections the class sees **nothing** (p = 0.42–0.59). Against small 0.5% corrections there is a difference: support per unit of selling in the last block, five events *before* the candidate — AUC **0.669**, z +4.0 against a noise level of 3.0 (p = 0.008). And it fades with depth: **0.653** for 0.5–1% corrections, **0.627** for 1–1.5%, **0.544** beyond. The deeper a pullback, the more it looks like a real end to the book — which is exactly the case where a bot would need to know. ## ③ The tail of a leg is visible — but so is its head Three more questions pressed on the same point. **When can a new leg be called?** The difference between the two sides of a pivot is present in the raw 63 numbers of an event from the very first event after it (AUC 0.26 on the strongest number, z −6.5, p = 0.000 against shuffled labels). A model on batches of events climbs to **0.727** at 6–10 events and stops. But its most confident batches contain **no** true leg starts at any batch length. Starts of up legs and down legs are identical to the class: it does not say which way the new leg went. **Do batches of one leg resemble each other more than batches of a neighbouring leg?** No — at equal distance in time and the same place in the leg, AUC stays at 0.5 (best 0.580, p = 0.183). What looked like a difference was the leg edge again, and whatever separates "our leg" from "the next one" turned out to be time, not the pivot. **Is this the tail of a leg?** The head and tail of the same leg are unrelated (Spearman ≈ 0 on six of seven features), while the tail of a leg correlates with the *neighbouring* leg's head at +0.75 to +0.81 — what is close in time is alike. A detector on the levels of the candidate alone reaches AUC **0.74–0.82** and precision at the top of **5.6–23.5%** against base rates of 0.6–4.2% — up to **×19**. Comparing with the leg's head only hurts. And the same detector separates a tail from a head at only 0.59–0.61 (p = 0.14–0.30): it catches **any** edge of a leg, not its end. The book knows it is at an edge. Whether the move is ending or beginning, it cannot say. ================================================================================ # The Order Book Along a Leg — Slow Legs, Thin Edges, and a Signal at the End That Beats Chance ×4.6 URL: https://marketflowresear.ch/articles/the-order-book-along-a-leg-slow-legs-thin-edges-and-a-signal-at-the-end/ Published: 2026-09-30 · Series: The road to Bot 7 · The class along the leg > We laid the seven features of our best order-book class along 554 zigzag legs of six coins. Every feature marks the edges of a leg, with the book thinning per unit of flow right before a pivot. The same features tell a short leg from a long one early — not the exact length, but its distribution. A memory network trained on "the last 5% of the leg" puts 23% of its loudest calls there, against 5% by chance. And the honest cost is written next to each number: detecting a new leg takes 12–16 events, a price-path detector still does better, and the zigzag labels themselves arrive late. ## ① Every feature marks the edges Study 28 measured the leg on price. Here the same pass is applied to `210×10-1×7d/d` — six derivative ratios between book levels and flow, plus the price derivative — over **554 legs** and 309,021 events on six coins. **Every one of the seven features marks the edges**, with |t| from 9.6 to 10.2 between edges and middle (the same measurement on noise gives |t| < 4). They split into two opposite groups. Flow-type features (flow per resistance, flow per support, price) are *higher* at the edges — a U-shape with its bottom in the fifth tenth and its top in the last. Book-per-flow ratios are *lower* at the edges and lowest precisely in the **last tenth** (0.343 against 0.466 mid-leg): just before a pivot, each unit of trading meets less standing book. The end of a leg is sharper than its start in both groups — the opposite of the price-based picture, where the start dominated. Length matters too. Long legs are **slow**: the amplitude of flow and price derivatives is lower (Spearman −0.59 to −0.61 with leg length), book-per-flow ratios higher (+0.54 to +0.60). The edge profile survives at any length; the level shifts, the difference stays. Same sign on all six coins. ## ② A new leg is visible after 12–16 events Asked whether a 2.3% reversal happened within the last X events, gradient boosting on the class reaches AUC **0.737–0.762** for every X from 3 to 100 on the unseen weeks — longer history does not make the class see a reversal better. What moves is the price of the answer: 95% precision at the top 1% of scores needs X = 100 and arrives **29 events** (1 h 42 min) after the pivot. The working middle is X = 30–39: **49–62%** precision at 12–16 events delay. The fastest windows (X = 5–8, delay 2–5 events) are right only 3–11% of the time. What works changes with the window: on short windows, the *mean* levels of support and resistance per flow; from X = 10 on, their *spread* — when a reversal is inside the window, the spread of those ratios drops, the same thinning seen in the last tenth. For comparison, the same detector on the price path (study 28) gives 0.830. Price is still the stronger description. ## ③ Short or long: the leg's length as a distribution Stage 1 found that feature level and leg length are linked, but measured the level over the whole leg. Taken causally from the first K events after a pivot, the link holds: split legs into five equal groups by the level of support-per-flow in the first 10 events and the median lengths run **238 → 372 → 476 → 483 → 565**. The quartiles overlap — the level moves the *distribution* of length rather than naming it. A model on the head of the leg plus the previous leg forecasts length with Spearman **+0.58** and AUC 0.806 by date, +0.44 and 0.716 on a held-out coin (K = 100); the median error is 162 events against 198 for the median. The class alone, with no price, already gives 0.697 on a held-out coin. The longer the leg has run, the better its end is seen (+0.32 at K = 10 → +0.50 at K = 100). On the unseen weeks, the detector plus this forecast catch 47 of 95 legs within their first 39 events — but with hundreds of false triggers inside legs, and a forecast of the end that is off by 112–563 events. An order of magnitude, not an event. ## ④ "The last 5% of the leg": 23% hits where chance gives 5% The last stage labels the final 5% of each leg and trains a memory network on 131 channels from seven classes (451 legs train, 103 validation). The best run — plain binary cross-entropy, positive weight 19 — gives AUC 0.714 and AP 0.151 on validation, and its output climbs **ninefold** from the second tenth of the leg to the tenth. Taking its loudest 5% of events, **23.2%** are truly in the last 5% of a leg: **×4.6** chance. A counter of events since the pivot, used the same way, scores 4.7% — worse than random, because its loudest events are the ends of the longest legs. The honest caveat is in the same table. The network also sees counters reset at zigzag pivots, and a 2.3% pivot is confirmed only once price has moved 2.3% away — a median of **80 events** (4.7 hours) later on validation. Removing the three counters costs AP 0.027; the class alone still hits **12.9%** at its loudest 5%, 2.6× chance. So the class carries the result and the labels amplify it. Shaped losses (focal, "close") only made the whole leg hum at 0.5; what helped was training longer and demanding silence in the first 50 events of a leg. The network memorises train almost completely (AUC 0.998) — early stopping on validation is what keeps it useful. ================================================================================ # A Leg Moves at Its Edges — and You See the New One Only After It Starts URL: https://marketflowresear.ch/articles/a-leg-moves-at-its-edges-and-you-see-the-new-one-only-after-it-starts/ Published: 2026-09-30 · Series: The road to Bot 7 · Edges of the leg > Split every 2.3% zigzag leg of six coins into tenths and measure where the price actually travels: 39% of the move happens in the first and last tenth, three times more per tenth than in the middle. The start of a leg reveals its direction and its volatility, never its length or its ending. A detector for "a new leg has begun" reaches 63% precision 21 events after the pivot and 98% after 31 — confirmation, not foresight. And twelve numbers about the price path beat every order-book class in the project at that task. ## ① Where a leg makes its move Study 01 found two things and stopped there: the move of a 2.3% leg gathers at its edges, and the number of events in a leg varies from tens to thousands. This study measures both to the end, with a method written so the same pass can measure any class of the project. The series is `210×10×7` on six coins, train and validation together, legs from the 2.3% zigzag on an EMA-10. Averaged per leg, the first tenth carries **22.5%** of the move and the last **15.3%**; the four middle tenths 6–7% each. Pooled over all legs, the two edge tenths hold **0.391** of the move and the four middle tenths 0.262 — per tenth, **2.98×**. The shape is the same pooled or per leg and on every coin (edge/middle 2.65–3.23). Direction changes the emphasis: down legs put more into the *first* edge (0.238 vs 0.154), up legs into the *last* (0.211 vs 0.183) — falls start abruptly, rises push through at the end. And length changes the edges: the shortest quarter of legs (11–212 events) holds only 0.237 at the edges, and their last tenth is essentially empty (+0.007) — they reach the pivot already spent. Leg length itself is spread over 200× (median **392 events**, 22.9 hours) and correlates with the size of the move only +0.46. ## ② What the start of a leg does and doesn't tell From the first events of a leg one can read its **direction** (0.978) and the **typical size of counter-moves** inside it (+0.60). One cannot read **when it will end** (+0.44, but a mere 4% better than the median), **how it will end** (−0.04 to +0.06), or its **largest counter-move** (−0.03). Rises and falls start as mirror images in shape but not in tempo: falls run on more frequent and larger events and keep their pace for eight events; rises fade after the first. The tail of the previous leg tells no more. It predicts the scale of the next start — spread, path, largest event (+0.55 to +0.77) — but **carrying one number across the pivot beats the model** on each of those targets (+0.59 to +0.86). Volatility simply continues through the reversal. How far the next start will go in percent, and how long the next leg will be, are not readable (+0.30 with a 37% *worse* error; +0.17). Predicting inside a leg says the same thing from another angle: the **size** of a mid-leg event is forecastable (Spearman +0.69 by date, +0.63 on a held-out coin, error 27–32% below the median), the path, the directed move and the share of events going the leg's way are not — every model loses to a constant. ## ③ Detecting a new leg: precision bought with delay The question "did the new leg start within the last X events?" gets AUC **0.80–0.83** for every window from 5 to 100 events on the unseen weeks. What changes is the label: at X = 5 it is true once per hundred events, at X = 100 once per five. So precision at the top 1% of scores rises by itself — 0.08, 0.12, 0.34, **0.63**, **0.91**, **0.98** — while the lift over the base rate stays at 5–8×. The model always does the same thing: it sees the break once it fits in the window. That makes the delay the real price. One true signal in three arrives about 11 events (40 minutes) after the pivot; two in three, 21 events (1.2 hours); nine in ten, 25 events; almost no errors, 31 events (1.8 hours). A median leg is 392 events, so that is its first 5–8% — and those first tenths carry 19% of the leg's move. **By the time the detection is confident, part of the edge move is gone.** The strongest single features describe the *previous* window — the path and spread of the old leg's violent end. The model recognises a new leg by the trace of the old one. On the unseen weeks with a threshold from training, precision is 0.65 pooled but 0.03 on SOL and 0.81 on XRP: one threshold for all coins is a crude setting. ## ④ Twelve price numbers beat every class The last step asked the same question in the language of each event class. On the same series, labels and window, **price beats the book**: 0.830 against 0.759 for `210×10×7`, 112 columns of levels and volumes. Across all 13 classes available on six coins, none reaches price; the best, `210×14×5` at 0.785, stands on a sparser series where the label is four times more frequent. On the common grid the best class is `210×10-1×7dc` at 0.764. Two more observations. A longer window does not change price's AUC (0.830 at 39 and 100 events) but *lowers* almost every class — averaging a class over 12–13 events per part blurs what it had. And the size of the input decides nothing: 32 columns give 0.726, 144 columns 0.752. Where classes help at all, their strongest columns are support levels — the same support that led rising legs in stage 3. The conclusion is the thread of this whole series: the order book knows the *size* of what is happening and recognises a turn once it is under way; which way the next move goes, and when the current one ends, stays out of reach from the event alone. ================================================================================ # The ±0.15% Pivot Zone — Seventeen Ways to Describe an Event, One Honest Ceiling of 0.70 URL: https://marketflowresear.ch/articles/the-pivot-zone-plus-minus-015-percent-seventeen-ways-to-describe-an-event/ Published: 2026-09-30 · Series: The road to Bot 7 · Pivot zone ±0.15% > Near every 2.3% pivot, price lingers within 0.15% of the turning level for a while — a median of 11 events, about 38 minutes, 2% of the whole series. Is that stretch recognisable from the order book alone? We asked gradient boosting on every event of six coins, with batches of 1 to 11 events and all 17 event classes this project has built. The answer is a consistent "a little": AUC 0.61–0.66 on the main class, 0.701 at best on raw book levels — and at a working threshold, 95 hits bought with 6,725 false signals. ## ① A zone defined by price, measured by the book The zigzag is the same as in studies 21–26: 2.3% on an EMA-10 of event prices. Around each pivot, price holds the turning level for a while, and that stretch is the **zone**: the continuous run of events around the pivot where the EMA stays within ±0.15% of its value at the pivot. Zones of neighbouring pivots never overlap — between two pivots price travels at least 2.3%. On six coins from 14 February to 6 September 2026 there are **718 zones** in 412,811 events: median length **11 events** (≈ 38 minutes), a quarter shorter than 7, the longest 61. Together they are about **2%** of the series — the base rate every result is compared with. The question is asked on **every event** with no filtering: does the batch of K events ending here lie entirely in one zone? The input is the raw numbers of the class for those K events, nothing folded. K grows until the batch fits into only half the zones — 11. Training is everything except 14 August – 7 September, which is the unseen validation window. ## ② Recognisable — statistically On `210×10-1×7d/d`, the class of the last several studies, gradient boosting recognises the zone on the unseen weeks with AUC **0.61–0.66** at every batch length — stable, never falling to 0.5. One event gives 0.642; eleven events, 0.655. That is 693 inputs instead of 63 for +0.013. The working point shows what that means. At 20% recall, precision is **3.4%** with single events (base 2.1%) and **1.2%** with 11-event batches (base 0.57% — longer batches fit fewer zones, so the label itself shrinks from 1,191 to 319 positives). The lift over the base is ×1.2 to ×2.2, at 38–68 signals per coin per day. By coin, ETH, SOL, XRP and BNB reach 0.71–0.72, while BTC and DOGE — the coins with the most zone events — sit at 0.61. The zone is a reversal zone only statistically: better than a coin, and at any usable threshold, one hit among dozens of false signals. ## ③ Seventeen classes: raw levels win, prices lose The zone, label, split, batch grid and model stayed fixed; only the description of the event changed — **17 classes** with a dataset (three families of different density, so the base rates differ by family). **Raw book levels describe the zone best**: `210×10×7` (ten blocks × seven levels per unit of volume) reaches **0.701**, and `210×10×9` 0.687, both at K = 11. Taking derivatives costs about 0.06 — for a zone defined by a *price level*, the level of the book is informative, its change less so. Derivative classes do best with single events; stacking derivatives adds nothing. The older families with 15 blocks of 14 seconds give 0.57–0.59. And the classes built on smoothed price — `210×210×4c`, the 13-EMA class that powered studies 12–17 — land at **0.50**; the EMA classes fall to 0.38–0.42, *below* a coin: what looked like a zone signal on training flips on unseen weeks. Even the best class does not make a trading signal. At the threshold taken from training, `210×10×7` fires **6,820** times on six coins over the unseen weeks and hits the zone **95** times, missing 224 zone batches: the band of false signals under the price chart is two orders of magnitude wider than the zone. The thresholds also don't transfer across coins — DOGE produces 389 false signals, ETH 2,300 on the same number of events. The zone is real and the book knows about it, weakly; what the book does not provide is a clean moment to act. ================================================================================ # The Filter That Would Lift Precision From 51% to 93% — and Why We Cannot Build It Yet URL: https://marketflowresear.ch/articles/the-filter-that-would-lift-precision-to-93-percent-and-why-we-cannot-build-it/ Published: 2026-09-30 · Series: The road to Bot 7 · The perfect filter we cannot build > Half of the reversal-confirmation signals are false, and they share one trait: they point into the middle of a leg. A filter that knows how far along its leg an event really is removes 45 of 49 false signals and not one true one — precision 51% → 92.7%. The catch is that "how far along" is only known in hindsight. Every causal estimator we built — trees, a memory network, ten loss functions, a 24-point grid — reaches an AUC of about 0.69 for "this is the last tenth of the leg", where the filter needs something near 0.95. With that estimate, the filter cuts true signals as fast as false ones. ## ① The idea works — with the true answer The confirmation ladder of the last two articles answers "was there a pivot N events ago?" at about 50% precision on unseen weeks — half the signals are wrong. This study asks whether a **second signal** can cancel the wrong half. The second signal is simple to state: take the event the ladder points at and say **what share of its leg it has travelled**, from 0 at the start to 1 at the end. A pivot is the end of a leg, so a signal pointing into the middle of one should be false. With the *true* share — known in hindsight from the zigzag — the idea works beautifully. At rung 43 (150 minutes after the pivot, four windows plus class, the threshold from honest training scores) there are 51 true and 49 false signals on the three unseen weeks. Keeping only signals whose event has travelled at least 90% of its leg: **51 true, 4 false — precision 92.7%**, recall unchanged. At rung 103, 73.3% becomes **97.1%**. The false signals really do sit in the middle of legs. ## ② The causal estimate cannot see the end of the leg The estimator gets only causal inputs: a counter of events since the last *confirmed* pivot, the five context numbers on four windows, and optionally the 62 class numbers. On the unseen weeks, by mean absolute error, **no set beats the constant 0.5** (best 0.2534 vs 0.2484): what the trees learned on training weeks does not transfer. They do see the end of a leg a little — AUC **0.653** for "this event is in the last tenth", against 0.552 for the counter alone. The class adds nothing (0.656), as in every study since 23. A memory network over 2,500 events of history does better — AUC **0.693** with four windows and the counter, and the only estimator to beat the constant on MAE. Ten loss functions (MSE, L1, Huber, rank, edge-weighted, staircase heads, tenths…) all land in 0.739–0.761 on the later part of validation — a spread of 0.022, pure selection noise. Stretching the output to the label's spread made the error worse at the same AUC: under a weak signal, hugging the middle is the correct behaviour. A 24-point grid over memory length, width, depth and learning rate: best 0.6930 against 0.6922 for the untouched control. Every model's best epoch is the first; they overfit from the second. ## ③ A weak estimate cuts the wrong signals Used as a filter, the estimated share does the opposite of what was hoped: it **cuts true signals faster than false ones**. At a threshold of 0.5 the trees' estimate removes 8 false and 5 true signals (51.0% → 52.9%); at 0.9 it keeps 3 of 100 signals and precision *falls* to 37.5%. Thresholding the network's output needs ranks — its scale is compressed and it almost never says 0.9 — and even then the best result is 52.9% at rung 43 and 76.9% at rung 103: gains of a point or three, paid for with a third of the signals. One more idea was tested: a second network trained to confirm reversals, used as an extra vote. At rung 103 it only hurts. At rung 43 it helps only at the very end of its scale — a 0.99 threshold gives 71.4%, but that is 10 of 93 reversals, one signal every eight days. The two models look at the same price context and tend to be wrong in the same places: at 0.9 the network cancelled 20 false signals and 23 true ones. The whole problem has collapsed into a single number: how well the last tenth of a leg can be recognised causally. The ceiling shows what each point of that AUC is worth — tens of percentage points of signal precision. The estimate sits at 0.69; the filter needs about 0.95. The next study attacks exactly this gap with a different definition of the reversal zone. ================================================================================ # Can a Memory Network Rebuild Context From the Raw Sequence? Not From the Order Book URL: https://marketflowresear.ch/articles/can-a-memory-network-rebuild-context-from-the-raw-sequence/ Published: 2026-09-30 · Series: The road to Bot 7 · Memory vs aggregates > Trees won the reversal ladder with hand-made aggregates: five numbers about recent extremes over four look-back windows. A memory network should not need them — the price change of every event is already inside the class, and integrating it would rebuild the whole context. We gave an LSTM 60 events of raw class, of price context, and of both. The class alone reached an honest AUC of 0.77; price context alone, 0.965. Adding the class to price made it worse. And trees on five aggregates still found reversals two and a half times more precisely than the network. ## ① The question: is the class enough? Studies 23 and 24 worked with **aggregates**: before any model saw the data, ten events were folded into medians, slopes and peak positions, and the context windows (200 to 1,600 events) were chosen by hand. A network with memory asks for none of that — it gets the sequence of events as is and must build long context itself. The question is not rhetorical. One of the seven features of the class is `d_price_avg`, the price change per event. Integrated over a window, it rebuilds the price path, and from the path, everything the context numbers contained. Does the network do it? The setup mirrors study 24: the first rung of the ladder ("a pivot three events ago", about ten minutes), windows of **60 events** (three and a half hours) taken at every event, six coins, split on 14 August. That gives 167,571 windows and 696 reversals. Three channel sets: the raw class (63 numbers per event), price context (the five context numbers on four windows, 20 channels), and both. An LSTM with 96 units and one logit; the epoch is chosen by the *honest* average precision from held-out-coin runs, and the threshold is set on those same honest scores — validation is never used for any choice. ## ② The class alone falls far behind price The gap is sharp. The class gives an honest AUC of **0.772** (0.735 on unseen weeks); price context, **0.965** (0.950). The network does not rebuild from `d_price_avg` what the ready-made position numbers provide. At the threshold fixed from training (30% recall), the class-only network raised **2,198 false signals** for 26 hits across 94 pivots on the three unseen weeks: precision **1.1%**. Price context: 32 hits, 275 false, **8.5%**. And **class plus price is worse than price alone** — 0.926 honest AUC, 6.1% precision, 17 hits. Sixty-three class channels do not just add nothing; they take capacity the network would have spent on price. One improvement over the earlier memory networks: with three times more positives (696 reversals instead of 223), the network stopped memorising grossly — honest 0.965 and validation 0.950 almost coincide. ## ③ Trees on five numbers still win Compared on the same rung and the same unseen weeks, gradient boosting from study 24 beats every network: **21.5%** precision on the five context numbers, **21.4%** on four windows, AUC up to 0.987 — against 8.5% and 0.950 for the best LSTM, even though that LSTM sees the same twenty numbers laid out over time. The reason is built into the setup. The network sees 60 events; the scale that decides whether a local extreme is the extreme of the leg is up to **1,600 events** — four days. Longer windows were not an option: beyond 60 events fewer than two hundred reversals would remain for training. So the LSTM here is not "the step after trees"; it is a different formulation that lacks the length it needs. Its hyperparameters were not searched either; a grid could lift the class-only network somewhat, but not across a gap of this size. A ±0.1% price tolerance lifts the price-context network threefold (8.5% → 27.1%): it points at the **level** of a reversal well and at its **moment** poorly — the same limit as trees on a single window. The practical conclusion is the one this series keeps meeting: the useful information about reversals lives in the position of price within the move over days, and that is best handed to a model directly, as a few well-chosen numbers. ================================================================================ # Pivot Confirmation on Three Unseen Weeks — Precision Holds, the Threshold Does Not URL: https://marketflowresear.ch/articles/pivot-confirmation-on-three-unseen-weeks/ Published: 2026-09-30 · Series: The road to Bot 7 · Held-out time > The reversal ladder of the previous article was scored on a held-out coin — but in the same weeks it trained on. Here the models trained on everything up to 14 August 2026 and were scored on the three weeks after, six coins, with the threshold fixed in advance from honest training scores. Precision did not fall: 51% two and a half hours after a pivot, 73% after six hours, on 88–93 reversals. What broke instead was the threshold itself — at two rungs of the ladder the models went completely silent while their AUC stayed above 0.9. ## ① A stricter test: held-out time, fixed threshold Study 23 measured everything on train with a held-out coin: the model had not seen that coin, but it had seen those very weeks. Here the test is held-out **time**: train on all six coins up to 14 August 2026, then score 14 August – 4 September. The ladder is unchanged — "was there a 2.3% pivot exactly N events ago?" — and each example lies wholly on one side of the split. Four input sets are compared: the class (62 batch features), the context (5 causal numbers on one 400-event window), four windows (the same five on 200/400/800/1,600 events, 20 numbers) and four windows plus class. The threshold is set at 30% recall on **honest** training scores — each training event scored by a model that had not seen its coin — and applied to validation as is. Validation is small and the article says so: **112 coin-days and 88–93 reversals** per rung. With that sample the error on a precision is several percentage points. ## ② Precision survives the move to new weeks At rung **43** (150 minutes after the pivot) four windows plus class give **55.0%** on train and **51.0%** on the unseen weeks; four windows alone, 49.9% and 49.1%. At rung **103** (six hours) validation is even higher than train: **73.3%** against 67.9%. Rung 43 is the working point: the highest recall (55–60%) at about 50% precision. Rung 103 is more precise but catches only 38–53% of pivots. A second score counts signals that miss the pivot *event* but point to an event within **±0.1% of its price** — a miss in time, not in the entry level. It matters most for the single-window context: at rung 103 its strict precision is 24.3%, with tolerance **56.9%** — 35 of its 144 signals sit on the pivot and 47 more on its level. Four windows barely need the tolerance (73.3% either way): one window shows *where*, four windows also show *when*. The class on top of four windows changes precision by a few points in either direction and halves recall — within the error. ## ③ The model separates — the threshold does not travel The failure that did appear is of a different kind. At rung 23 **three of the four** input sets gave no signal at all on validation; at rung 3 the four-windows-plus-class set was silent. Their AUC on validation was 0.91–0.99 — the models still rank reversals far above everything else — but the threshold taken from training ended up above the entire validation series. The ranking transfers; the absolute level of the scores does not. And the breakdown jumps between sets and rungs, so no single set can be fixed as "the" model yet. Per coin at rung 43 the picture is uneven but consistent: BTC hits 8 of 9 pivots, ETH 8 of 11, while XRP — with 31 pivots in three weeks — catches 11 and misses 19. One or two pivots per coin sit at the edge of the data, where the answer "a pivot 103 events ago" simply has not arrived yet. Two things carry forward. The confirmation ladder keeps its precision out of time, which makes it a real candidate for a trading rule. And its weak point is calibration: a threshold from the past will not always admit anything in the future, so a live bot needs a threshold that adapts, not one frozen at training time. Three weeks and ~90 reversals are still a short check — the numbers agree with train and with each other, but decisions need a longer validation. ================================================================================ # A Reversal Is a Place in the Move, Not a Shape in the Book — Five Causal Numbers Beat 62 URL: https://marketflowresear.ch/articles/a-reversal-is-a-place-in-the-move-not-a-shape-in-the-book/ Published: 2026-09-30 · Series: The road to Bot 7 · Where, not what > The edge of a leg really is different from its middle — in 85% of 600 legs, by a factor of about 3.8, with a coin-flip control at 0.51. Yet no single 10-event batch can be picked out of the whole dataset by its book numbers. Five tests later the reason is clear: what identifies a reversal is where you are in the move, not what the book looks like. Five causal numbers about recent extremes lift the hit rate 121-fold over the base; the 62 numbers of the class manage 3.8-fold and add nothing on top. Asked again every ten events with four look-back windows, "was that a pivot?" climbs from 26% after ten minutes to 71% after six hours. ## ① The difference is real — inside each leg Study 21 showed that *on average over hundreds of legs* the edge of a leg looks different from its middle. Study 22 showed that a *single* 10-event batch has no signature of its own. Both are true at once, and this study tries five ways to get the average difference out of the noise. **A local rank instead of a pooled baseline** — normalising each batch against its own neighbourhood to remove volatility regimes — did nothing: AUC 0.755 on a 1,000-event window against 0.744 pooled, and lower precision. Volatility is not why separation is weak. **A pair inside one leg** is where the effect shows plainly. Compare the five events at each end of a leg with the middle of *that same leg*: flow ratios are stronger at the edge in **85.3%** of 600 legs (median ×3.77), price moves in 83%, and book-per-flow ratios are weaker in 81–83%. The same method on random places gives 0.487–0.510. The end of a leg is slightly more distinct than its start here (0.78 vs 0.74), and edge width barely matters: 3 to 20 events all give 0.84–0.85. The pooled test asks "is this batch strong at all?" — and the dataset is full of strong batches. The in-leg test asks "is it stronger than the middle of its own leg?" Only the second matches what the leg profile shows. ## ② Longer batches help — four times slower than they should Averaging more events should shrink noise. It does, a little: the best AUC rises from 0.744 at 10 events to **0.767 at 60** (2.3–3.5 hours), and precision at 10% recall from ×4.3 to ×10.3 the base rate. But the gain is 1.10 where independent noise would give 2.45: neighbouring events are correlated, so each extra event brings less new information. Past 60 events it stops — a 100-event batch covers half a leg and mixes the edge with the middle. ## ③ Where you are beats what you see: ×121 vs ×3.8 The fourth and fifth tests stop describing the batch and describe the **move** instead, causally — only from what is known at that moment. Rolling extremes of the smoothed price over the last 400 events give: how far the move has run up from the low and down from the high (in units of the 2.3% threshold), and how many events since each extreme. How far the move has gone matters little (a run past the threshold doubles the base rate, ×1.65). **When the last extreme happened** matters enormously: batches where the rolling low was 3–5 events ago hold 180 of 2,509 reversals — a base rate of 7.2%, **×34.9** the average. Part of this is geometry: the labelled batch ends three events after the pivot, and the pivot *is* an extreme of the smoothed price. That is exactly the point — the context finds **candidates**; 93% of them never become a 2.3% reversal, because confirmation lies in the future. Given to gradient boosting, the five context numbers score AUC **0.982** and ×121 the base rate: at 20–30% recall, **one in four** flagged batches is a reversal, at about one signal per coin per day. The 62 class numbers: ×3.8, with dozens of false signals a day. Class plus context is *worse* than context alone (×102): 62 weak inputs on 437 positives are noise for the trees. A cheat run with the true "events since pivot" reaches 0.9999 — the task is solvable once you are given the answer, and the gap between 0.971 and 0.9999 is exactly what cannot be known causally. ## ④ Ask again: 26% at ten minutes, 71% at six hours The last test turns the detector into a procedure. Instead of asking once, ask at every rung of a ladder: **was there a pivot exactly N events ago?**, for N from 3 to 203, with a held-out coin for scoring. With a single 400-event window the answer never improves: 22–35% at any delay. The reason is leg length — a 2.3% pivot is the extreme of the *whole* leg, median 423 events, and within 400 events "price fell 2.3% from the high" happens many times inside one long leg; only the first was the pivot. Four windows (200, 400, 800, 1,600 events) tell the leg's extreme from a local one, and then waiting works: **26%** after ten minutes, 47% after 80, 57% after three and a half hours, **71.5%** after six. Beyond about 100 events the numbers wander between 47% and 68% — sampling noise at 30% recall. Adding the class numbers again changes nothing. So the working scheme is: flag a candidate at once, then re-ask every ten events and let the confidence grow. It is a confirmation machine — it tells you a turn has happened, with increasing certainty, not that one is coming. That distinction, and the gap between the in-leg difference and single-batch detection, set the questions of the next studies. ================================================================================ # A Reversal Has No Signature of Its Own — One in Four Ordinary Stretches Looks Stronger URL: https://marketflowresear.ch/articles/a-reversal-has-no-signature-of-its-own-in-the-order-book/ Published: 2026-09-30 · Series: The road to Bot 7 · No reversal signature > Around a 2.3% pivot the order book changes in multiples: flow ratios two to five times bigger, book-per-flow ratios three to seventeen times smaller. That sounds like a fingerprint. It is not. One in four continuous 10-event stretches far from any pivot is stronger still, the strongest is 47 times stronger than the strongest reversal, and a neural network on all 630 numbers of a reversal batch reaches the same AUC as a straight line: about 0.70. The reversal is a shift of the same distribution, not a different kind of event. ## ① The edge of a leg is five events This study works with one class, `210×10-1×7d/d` from the previous article: seven derivative ratios over nine 21-second blocks. Along a leg the seven features spread widely near both pivots and bunch together in the middle. The first question was practical: how many events from each end of a leg count as its "edge"? Three different measures gave one answer: **five events** (1% of an average leg is also 5.3 events). The spread falls monotonically with the width of the edge — no peak in the middle — and five events keep 0.69 of the maximum 0.71. The end of a leg separates features less than its start (0.62–0.66 vs 0.69–0.71), the same asymmetry as before: the trace of a reversal is clearer than the approach to the next one. All the spread is carried by magnitude (`abs` 0.694); smoothness sits *below* chance (0.313). The reversal zone was then fixed as seven events before the pivot, the pivot and two after — 10 events. Across six coins it covers **1.91%** of the 402,725 events (701 pivots). Inside it the direct ratios (flow per level) are 2–5 times their typical size, the inverse ratios 3–17 times smaller, and price moves only 1.3–1.6 times more — the book changes in multiples while the candle barely grows. The peak is the pivot event itself. ## ② Strong is not special If size were the signature, the strongest stretches of the series would be reversals. So the series was scanned with a 10-event window, one step at a time, keeping only windows that **never touch** a reversal zone — 230,262 of them. **24.9%** of those windows are stronger, on the direct ratios, than the median reversal batch — every fourth stretch, stable across coins (19.8–34.0%). On BTC the strongest non-reversal stretch scores 766,306 against 16,169 for the strongest reversal: **47 times more**. And the map of the top 1% of these stretches is literally "a reversal, only brighter": the same pattern, five times more intense, with no pivot anywhere near. So the size of the moves does not define a reversal. What would have to separate them is something else — which is what the rest of the study looks for. ## ③ Nothing unique: every test lands at 0.70 Four ways to find a signature, each one more demanding. **Models on the raw batch.** All 630 numbers of a reversal batch into a logistic regression and a small network. Validation AUC **0.695** and **0.687**; the network scores 1.000 on train — it memorised 437 reversals with more parameters than examples. Taking the most confident batches gives about 5% reversals instead of 2%. A UMAP of the batches shows reversals scattered through the whole cloud, with no region of their own. **62 hand-made features** per batch — magnitudes, ratios, spreads, and "turn" features built to catch a change of direction inside the batch. The best single feature reaches 0.744. The turn features: **0.51–0.56**, a coin. A sign change inside the batch is no more frequent at a reversal than anywhere else. Only one of 437 reversals, on BNB on 1 June, lies outside the range of ordinary stretches on any feature. **A tighter threshold.** If reversals had a border, precision would climb toward one behind it. It stalls at **1.1%**: the five reversals that pass the strictest cut arrive with 440 ordinary stretches that pass it too. **Trees and neighbours.** Gradient boosting on all 62 features, trained on five coins and scored on the sixth: AUC 0.727, and no reversal scored above all 204,348 others. In the 62-dimensional space the nearest *ordinary* batch is usually closer to a reversal (median distance 3.66) than the nearest other reversal (4.65). The reversal is a **shift**, not a different nature: the same distributions, displaced — flow ratios up, book ratios down. Three unrelated formulations stop at the same ~0.70. That number is the property of the class, not of the model, and it is what the next studies try to break with better questions rather than bigger networks. ================================================================================ # Derivatives of the Order Book — Reversals Leave a Trace, Not a Warning URL: https://marketflowresear.ch/articles/derivatives-of-the-order-book-reversals-leave-a-trace-not-a-warning/ Published: 2026-09-30 · Series: The road to Bot 7 · Derivatives of the book > We rebuilt the basic event of this series from scratch: 210 seconds cut into ten 21-second blocks, book levels divided by the volume of their own block, then first derivatives from block to block — on six coins, 402,731 events. The new description sees reversals clearly: around a pivot there is more flow and a thinner book per unit of that flow. But almost all of it sits in the first tenth of the next leg. The book reacts to a reversal far more than it foretells one. The last class of the family, derivative over derivative, lifts a detector of the reversal zone to AUC 0.700 on fresh legs — and becomes the workhorse of every study that follows. ## ① A new family of events Every earlier study described an event through normalised differences between the two sides of the book. This one builds a new family of classes to look at the book in its own units: - `210×10×9`: the same 210 seconds cut into **10 blocks of 21 seconds**, the eight book features plus price. - `210×10×7`: each book level **divided by the traded volume of its own block** — resistance per unit of buying, support per unit of selling — so a quiet block and a violent one are comparable. - `210×10×7dc`: **first derivatives** of those seven series from block to block. - `210×10-1×7dc`: the same without the first block, which is the only one that looks outside its own event. The datasets cover BTC, ETH, SOL, XRP, BNB and DOGE from 14 February to 1 September 2026 (XRP and DOGE from 5 March), split by date on 14 August: **356,357** events train and **46,368** validation. A block with no trades on one side gives NaN; its frequency follows liquidity — 2,142 values on BTC, 108,706 on DOGE — and it turns out to be the main practical limit of the whole family. ## ② Size, not sign — and it is after the pivot The first comparison was events within ±10 of a 2.3% zigzag pivot (EMA-10) against the rest of their legs. Signed derivatives do not separate them at all (AUC 0.475–0.514). **Magnitudes do**: near a pivot there is more flow (`|d vol buy|` 0.619) and a thinner book per unit of that flow (`|d resistance|` 0.344, i.e. the other way). A batch of 20 consecutive events — 70 minutes — sees it three times better: 0.756 and 0.233, growing monotonically with batch length and holding on every coin. Near a reversal the book and the flow also hold each other more tightly (+0.17 in correlation), while the link between book levels and price weakens. Then the same features along the leg, tenth by tenth. **The whole difference sits in the first tenth.** The price derivative has a mean rank of 6.88 of 10 there (7.78 on 20-event batches), the other nine tenths lie in a band of 5.1–5.6, and the first tenth beats any other in 70–79% of legs. The last tenth, *before* the next pivot, is only slightly raised and loses to the first in 70% of legs. That changes the reading. A ±K window around a pivot picks up both the end of one leg and the start of the next — and almost all the effect comes from the side after the reversal. The features **react** to reversals more than they foretell them. For forecasting that is bad news, and it is the honest one. ## ③ The broken side of the book Split by direction, the book is mirror-symmetric. After a **bottom** (an up leg starts), it is the resistance side that collapses in the first tenth: `|d resistance|` rank 3.49, its balance 3.63, while support is barely touched (4.75, 5.46). After a **top**, the opposite: support 3.51 and 3.70, resistance 4.14 and 4.91. The AUC between directions is 0.673 and 0.362 on a single event and grows to 0.775 and 0.753 on 20-event batches. Along the whole leg the picture is a bowl: price and volume moves are strongest at both ends (rank 14.4 of 20 at the start, 11.4 at the end, 8.9 in the middle), book levels form the mirror bowl, and the direction difference lives only in the **first 5%** of the leg — after that everything returns to 0.5. Volumes and price do not tell directions apart at all (0.44–0.56): the burst at a reversal is the same whichever way the market goes next. A warning learned on the way: separating a bottom reversal from a top one looked perfect — AUC **0.997** on the sign of the price derivative. It is an artefact. The zigzag stands on an EMA-10 of price that lags by 4–5 events, so when the EMA reaches its minimum, the raw price has already been rising for several events. It fades with batch length (0.457 at 80 events) and says nothing about the market. ## ④ Derivative over derivative: 0.638 → 0.700 The family then got two compact classes. `210×10-1×2d` folds each side into one ratio: `d_up = d vol buy / d resistance` and `d_down = d vol sell / d support`. `210×10-1×7d/d` adds the four inverse ratios — level change over its own volume change — and carries the price derivative: **7 features × 9 blocks**, all dimensionless, measured by ranks because a ratio of two derivatives is unbounded. The test is a **reversal zone** inside the leg — its first 5% and last 10% — against the rest, with each event ranked *inside its own leg* so coin and regime are removed. A logistic regression on the two-ratio class reaches **0.638** on fresh validation legs (0.635 on train: no overfitting, but no margin). On the seven-ratio class it rises to **0.662 → 0.680 → 0.700** with batch length, train still below validation. The inverse ratios carry the gain: the biggest weights are the absolute and step changes of *support balance per unit of selling* and *resistance balance per unit of buying*, plus the price derivative. All the power is in magnitude and step (`abs`, `step`, `range`, `std`: 0.59–0.66); smoothness says nothing (0.49–0.52). The start of a leg is still seen better than its end (0.688 vs 0.632). The class is a trace-detector more than a forecaster — but it is the best description of the book this series has built, and `210×10-1×7d/d` is the class every following study uses. ================================================================================ # Change the Question, Not the Network — "Will the Leg End Soon?" Scores 0.73 Where "Which Tenth?" Scored Nothing URL: https://marketflowresear.ch/articles/change-the-question-not-the-network-leg-end-hazard/ Published: 2026-09-30 · Series: The road to Bot 7 · Ask what the data answers > The memory network of the previous study learned to count instead of reading the market. We opened its loss function and found why: counting was the exact optimum. Then a plain perceptron settled it — the 60 order-book numbers of an event carry zero information about which tenth of the leg it sits in. They do carry information about something else: whether a pivot is close. Rebuilt around that question — four horizons, one monotone curve — the same data scores an average AUC of 0.73 across six coins. The order book shows the exhaustion of a move. It still does not show its direction. ## ① The loss never asked for class 10 Study 19 ended with a network that never once called the end of a leg on 42,192 events. Rather than tune it, this study looked at *what it was minimising*. The loss rewarded a staircase that never jumps and never goes back — and its minimum is reached by **any** non-decreasing sequence with steps of at most one, including a constant. With a label defined by the leg's total length (known only to the zigzag) and a loss that never demands reaching the top, a steady count from a known start is not a training failure. It is the exact optimum of that pair. The repairs were done properly anyway. A model-driven reset gave no learning signal, because `if said == 10` has no gradient; soft gates `h ← h·(1 − p₁₀)` fixed that. An overfit test on 2,000 events proved the training loop works (similarity 0.942). On the full series nothing moved. Then the decisive check, with no memory at all: a two-layer perceptron, event → tenth, legs never split across train and validation. **The 60 book features alone: 0.2927 similarity, 0.107 accuracy — exactly random.** A single integer, events since the leg started: 0.5625. Both together: slightly worse than the counter alone. Knowing the elapsed time removes 39% of the uncertainty about the tenth; nothing in the data removes the rest, because a short leg's second tenth and a long leg's first are indistinguishable at the moment you are in them. ## ② Ask "is a pivot close?" — and the features wake up The tenth of a leg is defined by its full length. "A pivot is close" is a local property of price, visible from the event itself. Same perceptron, same features, same legs: the question "does the leg end within the next N events" gives AUC **0.644–0.658** for N = 5–20 on the features alone, while the counter drops to 0.54. The roles swapped: on this target the market does the work and time adds little. The signal is strongest on short horizons; wider windows pull more of the leg's middle into the label. So the network was rebuilt to answer this question. Four outputs — P(ends within 10), 40, 160, 640 events — form **one monotone curve**, a distribution of "events left", guaranteed non-decreasing by construction (each output is a conditional hazard on top of the previous). The fourth horizon is there for a reason: with only three, 73% of events fall into the "more than 160" tail where every estimate collapses to one number; adding 640 raises the ceiling of the method from 0.765 to 0.951. ## ③ One small validation set almost hid the result For several sections the reference number was an AUC measured on BTC after the split date: 3,800 events, **six pivots**. The one-horizon model scored 0.604 there. Run on all six coins, the same model averaged **0.710** — BTC was the worst of the six, not the typical one. Then a better-looking epoch appeared, 0.703 on BTC; on six coins it was **0.051 worse**, collapsing by two tenths on SOL and XRP. With six pivots, the maximum of AUC over epochs is mostly noise. The fix: choose the epoch by the mean AUC of all six coins after the split — 28,870 events and 63 pivots. Under that rule a hyperparameter grid that promised +0.073 on reduced data delivered +0.010 on full data, and the four-horizon model beat the single-horizon one on the same question (0.733 vs 0.720 on the shortest horizon; **0.742 averaged over horizons**; the 640-event horizon alone 0.799). Memory helps, but modestly: +0.022 over the memoryless net on the same split. The pooled AUC over all coins (0.76) is inflated by differences between coins, so the per-coin mean is the honest number — and coins cannot be ranked against each other by AUC, because the label is far more frequent on some. ## ④ What the event shows before a pivot: uniformity Which part of the event carries the signal? Averages carry nothing: 0.49–0.52 for every feature. The **range across the 15 blocks** of the event does — volume balance alone scores **0.649** on train (0.702 on validation), against 0.733 for the whole memory network. Before a leg ends, the event becomes internally uniform: its 14-second blocks stop differing. That is what "exhaustion of a move" looks like in this data. Top and bottom pivots show it equally (0.655 vs 0.645 on 600 train pivots; the apparent gap on 63 validation pivots is sample size). Feeding the range explicitly adds nothing (−0.004 mean), because the network already builds it from the same blocks. Two more questions complete the picture. A mirror detector — "a pivot happened within the last N events" — is *harder* (0.612), because the evidence sits in memory and the network does not hold a count from a pivot it has to recognise itself. And direction: "will the next pivot be above the current price" gives **0.563**, with memory adding 0.001. The model's own resets never fired once in the whole study. The order book shows that a move is running out; it does not show which way the next one goes. ================================================================================ # A Memory Network Asked "Is the Leg Over?" Learned to Count, Not to Read URL: https://marketflowresear.ch/articles/a-memory-network-that-learned-to-count-not-to-read/ Published: 2026-09-30 · Series: The road to Bot 7 · End of the leg > An LSTM with attention walked each 2.3% zigzag leg event by event and, at every step, said how far along the leg was. Across five label designs, one coin and then six, it never once placed its end-of-leg signal inside the last tenth of a fresh leg. What it learned was a clock: a steady count from the start of the leg. When the zigzag stopped handing it that start — memory reset only when the network itself called a pivot — it did not call a single one in 42,192 events. ## ① A new question: the whole leg, event by event Studies 16–18 judged each event through a window of fixed length and asked "where in the leg are we". This one changes the unit. The network gets a **whole leg**, from the event after one pivot to the next pivot, event by event, remembers everything it has seen, and at each step outputs one number: is the leg ending here? The end of a leg is the reversal. The inputs are `210×14×4c` — each event as 15 blocks of 14 seconds × 4 book features, 60 numbers — on BTC up to 29 August 2026 (43,859 events). Legs come from a 2.3% zigzag on a 90-event EMA of price: 50 pivots, **49 legs**, median length 709 events. The "end zone" is measured by the leg itself: the last 10% of its events *and* the continuous stretch next to the pivot where price is within 10% of the leg's range — 11.9% of events. Memory is reset to zero at the start of every leg; padding never enters the LSTM, so the network cannot read "how much is left" from the sequence length. A causal attention layer on top lets it look back over the whole leg so far. The split is by date: legs whose pivot is on or before 14 August 15:27 go to train, the rest to validation. ## ② It shouts "end" all the time Under a positive-class weight of 7.6, the cheapest answer is to keep the end-of-leg probability above threshold almost everywhere. On one 877-event leg it crossed the threshold 550 times. So the rule "the first crossing is the signal" fires near the *start* of the leg — 435 events before the pivot on validation, 765 on train — and the number of legs where the signal landed in the end zone is **zero** on both. A baseline that simply says "the leg ends after the median length" beat it on train (3 of 42). Four more designs followed. Ten classes — which tenth of the leg we are in — instead of a yes/no zone. A faster 10-event EMA under the zigzag, which doubles the legs to 87. Both together. None moved validation hits off zero; the best class accuracy was **0.136** against 0.10 for random, with an average error of two tenths of a leg. The first-ever hits — 5 of 81 legs — appeared on train only. With 6 or 7 validation legs the standard error was ±0.19–0.20; nothing could be proven either way. ## ③ Six coins, 602 legs — the step became a ruler To get statistical power the training set grew to **all six coins: 602 legs, 332,891 events**. Two penalties shaped the output into a staircase — no jumps over a class, no steps backwards. They worked perfectly: zero jumps, 99.0% clean +1 steps on train, and the same on fresh data. And that is exactly the problem. A smooth staircase minimises the penalty regardless of the features. Class accuracy dropped to **0.106** on train and **0.101** on validation — random for ten equal classes. The network had learned to count evenly from the start of the leg at the training pace, not to read the market. A clean test made this plain: 14 August – 2 September 2026, all six coins, legs the model had seen removed — **84 fresh closed legs**. Class accuracy 0.115, **zero** hits, the output never reaching class 10. The only number above chance, "peak in the end zone" at 28 of 84, turned out to be leg length: 23 of the 28 are on XRP and DOGE, whose fresh legs were two to four times *shorter* than in training. On a short leg a counter is still rising at the pivot; on a long one it tops out mid-leg. Nearly zero peaks where legs were longer. ## ④ Take away the zigzag's gift One advantage had been given for free all along. A 2.3% pivot is confirmed only after price moves 2.3% away from the extreme, yet every leg entered the network with a clean memory exactly at its first event. Live, nobody knows where that first event is. So the last test removed it. The same trained weights walk the series event by event without cutting it; memory resets only when the network itself says "class 10 — pivot here", with a safety cap of 3,000 events and a 3,000-event warm-up before the window. No zigzag, no scaler, causal attention; the zigzag stays only as the answer key. Result on 42,192 events of six coins: **zero self-called pivots.** All 11 resets came from the cap, and 3 of them happened to fall in an end zone — 3.6% of legs, below the 10% that chance would give. Class accuracy fell from 0.115 to 0.110 and the error grew from 2.16 to 2.43 tenths: that difference is precisely what the zigzag had been contributing. A label defined by the leg's length is only knowable to the zigzag. The lesson carried forward: a target that can be minimised by counting will be minimised by counting — the next studies change the question, not the knobs. ================================================================================ # Four Numbers per Event and a 28-Cell Answer — Where the Signal Really Came From URL: https://marketflowresear.ch/articles/four-numbers-per-event-and-a-28-cell-answer/ Published: 2026-09-30 · Series: The road to Bot 7 · Four numbers, 28 cells > The previous networks read each book feature through 13 exponential averages and topped out at a correlation of 0.29 with the leg target. Strip the averages away and the same features, raw per event, correlate at 0.09. So the link was made by the smoothing, not by the snapshot. We then gave a transformer six coins, 345,000 training windows and a new kind of output — 28 cells instead of one number — to stop it hiding in the middle. It stopped hiding. It did not start hitting: 5.4% of real pivot-zone signals, with false calls a day away. ## ① The snapshot barely knows the leg Studies 16 and 17 fed their networks a 13 × 4 matrix: four book features, each smoothed by 13 EMAs up to 130 events. The strongest single link with the target there was |r| = 0.294 — volume balance under a 130-event EMA. This study asks how much of that is in the features themselves. The class here is `210×210×4c`: one event, four numbers, no averaging — book balance, change of balance, volume balance and the price feature, all in [−1, 1]. The target is the same leg of a 2.3% zigzag on a 90-event EMA of price. The answer on BTC train (23,166 events): the strongest feature is volume balance at **−0.092**, three times weaker than its smoothed version. The link was made by the smoothing. That makes sense: four numbers describe 210 seconds of the book, while the target lives on a 5-hour EMA of price. Without averaging, feature and target are simply on different time scales. The signs agree with study 16 on every variant: balance and its change positive, volume balance and price feature negative. ## ② Smooth each leg by its own length The target twitches between pivots, and earlier studies calmed it with one fixed window for all legs. But 2.3% legs vary enormously: median 802 events, shortest 227, longest 2,431. One window undersmooths long legs and flattens short ones. So here the window is set **per leg, equal to the leg's own length** — centred, so there is no phase lag. Looking forward is fine for a *target*, which is labelled in hindsight anyway; it would be a leak for a feature, and none is smoothed this way. Pivot zones are left untouched and nothing crosses from one leg into the next. It is the strongest smoothing of the whole ladder — median window 802 events — and the only one that *added* to the link on train: volume balance **−0.0957**, 104% of the raw target's −0.0921; no fixed window did better than 98%. The honest caveat is in the same table: over all 39,879 events the gain disappears (83% kept), so this is an observation on train, not a ready target. What it does show is that the obstacle was the *uniformity* of the window, not its size. ## ③ 28 cells instead of one number The minimum of MSE on a noisy target is the conditional mean, which is why every model so far clustered near zero: saying −0.9 and missing costs more than saying nothing. So the output changed. The range [−1, 1] is cut into **28 cells**: the two edge cells are fixed at |y| ≥ 0.80 — literally the pivot zone — and the 26 in between are quantiles of the target, about 3.5% of events each. The label is soft (0.70 on the true cell, 0.15 on each neighbour), the loss is cross-entropy, and a "bottom" or "top" call is simply the most probable cell being 1 or 28. Training moved to **all six coins** with gaps filled — 387,990 events, split by date (train up to 10 August, test after), about 345,000 training windows. Four transformers differed only in window length, under the same wall-clock budget. On test (41,462 events): **K = 128** is best with 264 bottom hits and 105 top hits — **369 of 6,783 real edge signals, 5.4%**. Longer windows are strictly worse (369 → 289 → 223 → 0), because attention costs K²: in the same 40 minutes K = 1024 saw the data 7 times, K = 128 sixty. The model is not silent — it called "top" 3,374 times against 1,243 real ones — but a false call lands on average **444–890 events** (about a day or more) from the nearest real signal of the same cell. Unusable as an entry. Four numbers per event are too few; the next studies change the features, not the length of the window. ================================================================================ # Same Data, Different Readout — How a Transformer Fails Differently From an Attention Query URL: https://marketflowresear.ch/articles/same-data-different-readout-transformer-vs-attention-query/ Published: 2026-09-30 · Series: The road to Bot 7 · Readout > We repeated the previous study exactly — same 2.3% zigzag target, same pivot zone, same loss, split and seed — and changed one thing: how the network reads its own sequence. Averaging the 13 steps instead of letting a learned query pick them cut the error from 0.554 to 0.476 and made "vertex" calls 44% precise instead of 3%. Tuning then turned the same model into a noisy caller again. And past the end of the dataset, both readouts lose the direction. The readout decides how a network is wrong, not whether it is right. ## ① Averaging vs a learned query The setup is identical to the previous article: 13 EMA periods × 4 book features per event, a 2.3% zigzag on a 90-event EMA of price as the target, the pivot zone `|y| ≥ 0.90` within ±40 events, a spread-penalised weighted MSE, a time split and seed 0. Every number here compares directly. The only difference is the readout. Both networks run the same `TransformerEncoder` over the 13 periods; the `wattn` net then weights the steps with a learned query, the transformer simply takes their **mean**. With default settings the mean readout stays closer to the constant instead of stretching: test MAE **0.476** (wattn 0.554, constant 0.479), R² **−0.046** (wattn −0.462). The price is spread — 0.629 of the target's against 0.969. And the character of the errors changes completely: the transformer says "vertex" **16 times on test and is right 7 times** — 43.8% precision — while wattn said it 798 times and hit 25. The flip side: it catches only 1.1% of the zone. It mostly stays silent. ## ② A grid that found one lucky run Stopping at epoch 3 was a hint that the settings deserved a search, so the transformer — unlike wattn — got the full procedure: a coarse grid, a fine grid around the best, then training length. The coarse grid had 24 configurations; **21 hit the zone zero times** on validation, 14 of them stopping after 2–8 epochs. The best (width 64, 2 layers, dropout 0.1, lr 3e-4; 101,185 parameters) caught 49 of 275 zone events. The fine grid around it, 27 neighbours: 21 with zero hits again, nothing better. That is not a plateau around an optimum — it is one run that broke away from the rest. Patience matters too: with 10 epochs of patience the same config stops at epoch 3 and catches nothing; with 30 it reaches epoch 20 and catches 17.8%. On test, tuning buys hits with noise: the output spread lands exactly on the target's (1.064), the zone share rises fourfold to 4.6% — and the model now says "vertex" **1,758 times** on 9,861 events, precision 1.7%, with MAE 0.630 and R² −0.851. Neither setting gets closer to the vertices themselves: 0.840 vs 0.843 remaining distance in the 0.1 band. ## ③ Longer windows and ten unseen days With windows of K = 5 … 50 events, context again adds neither accuracy nor direction: MAE stays at 0.51–0.58, sign at 52–57%, with no trend in K. Hits jump — 9.1% at K = 5, 19.9% at 10, zero at 15–25, 25.7% at 45, zero at 50. The transformer hits more often than wattn at the same K, but the zeros sit in the same places: the same instability with a larger amplitude. The best windowed model (K = 10, 206,465 parameters) was chosen at **epoch 1** — essentially an untrained model catching zone by scatter. The saved single-event model then met 16–27 August 2026. It caught **39 of 184** zone events — 21.2%, more than validation and test combined — but only because it called "vertex" 509 times on 2,945 events (precision 7.7%), with a median of 281 events (≈ 16 hours) from the nearest real pivot. Pearson **−0.150**, sign 45.8%, R² −1.49: past the end of its data, the model is worse than a coin, exactly like wattn (−0.226, 44.9%). The conclusion is architectural and short. The readout changes *how* a network is wrong — cautious and precise, or bold and noisy. It does not change *whether* it holds the direction out of sample. Both networks hit the same ceiling as the correlations in study 11: about |r| ≈ 0.29 between these features and this target on train, and nonlinearity inside one event does not raise it. The next step is not a third architecture but different features. ================================================================================ # A Network That Found the Pivot Zone — Only Where It Was Trained URL: https://marketflowresear.ch/articles/a-network-that-found-the-pivot-zone-only-where-it-was-trained/ Published: 2026-09-30 · Series: The road to Bot 7 · Pivot zone net > We asked an attention network to do one specific thing: tell when price is near the end of a 2.3% zigzag leg — within 10% of the pivot and no more than 40 events from it. On the weeks it trained on it caught 65% of those zones. On validation, 4%. On test, 3.8%. On ten days after the dataset ended, its correlation with the target turned negative. This is a measured negative result, and the measuring tool it produced — the pivot zone — is what we carry forward. ## ① Measure the distance to the pivot, not the average error The target is the zigzag of this series at its larger scale: pivots of a **2.3%** zigzag drawn on a 90-event EMA of price, and each event's position in its leg rescaled to −1 at the low pivot and +1 at the high one (min-max, so the distance to a vertex means a distance in price). The inputs are the 13 × 4 matrix of averaged book features from the previous article. The question was not "what number does the model output on average" but **does its output reach the vertex**. So every report carries a second metric: the **pivot zone**, defined by two numbers — `|y| ≥ 0.90` *and* no further than **±40 events** (about 2.3 hours) from the pivot. The band alone is not enough: in a long leg price can fall back almost to its start, and `|y| ≥ 0.95` occurs 972 events away from any pivot. With both conditions the zone takes **2,624 events, 6.5% of the series**, exactly one window per pivot, and keeps the smoothed price within 1.27% of the vertex. A model "says vertex" when `|p| ≥ 0.90`. Hits, misses, false alarms, and — where it spoke — how many events it was from the nearest pivot. ## ② One event in, 26,049 parameters — memorisation The network is `wattn` — attention over the 13 EMA periods with a learned query for the readout, 26,049 parameters, trained with a spread penalty so its output is not squashed to the middle (output spread 0.969 of the target's). The spread came back; the vertices did not. On the training weeks the model nearly reproduces them: the remaining distance to the vertex in the zone is **0.161** against a floor of 0.035, and **1,049 of 1,606** zone events are hit. On validation, **12 of 275**. On test, **25 of 653** — while the model said "vertex" **798** times, a precision of 3%, with a median of **252 events (≈ 15 hours)** between a call and the nearest pivot. It sees tops in the middle of legs. Over the whole test segment: MAE 0.554 against 0.479 for a constant, R² −0.46. Only the sign (57.1%) stays above a coin. Upper vertices come out better than lower ones (0.73 vs 1.06 remaining distance). 26 thousand parameters on 23 thousand events is enough to remember, and not enough to generalise. ## ③ Smoother target, more context — no curve Two fixes were tried on the target and the input. **Smoothing between zones.** The leg target twitches between pivots. Of eight ways to calm it, a moving median removed reversals (×563) but not roughness (×1.15), and a straight line through the leg killed the link to the features (max |r| from 0.294 to 0.241). An EMA did both jobs: a 20-event EMA cut the oscillation **×4.7** while slightly *raising* the mean correlation with the features (0.1725 vs 0.1667). The cost is a lag of about half the period. **A batch of events.** Instead of one event, the network saw windows of K = 5 … 50 events (17 minutes to almost 3 hours), on a dataset with time gaps filled so long windows survive. Neither MAE nor sign grows with K. Hits jump: 6.8% at K = 5, 10% at K = 10, **zero from 15 to 35**, 18.8% at 45, zero at 50. Neighbouring settings giving opposite results is the signature of unstable training — the model either calls vertices often or never — not of a useful context length. ## ④ Ten unseen days: the sign flips The two finalists after a grid search: **K = 10** (width 64, one layer) catches 12.3% of the zone on validation with sign 61.8% and Pearson +0.226; **K = 45** (two layers) catches 18.8% with Pearson +0.291. Dropping the one or two weakest features even helps a little (+2.6 and +0.9 points of hits). Then the models met 16–27 August 2026 — raw data outside the dataset, rebuilt through the same chain. Both flip: Pearson **−0.211** and **−0.232**, sign 45.7% and 46.2%, R² about −1. The K = 45 model, best on validation, hit the zone **zero** times out of 77 events. The K = 10 model hit 24 of 153 — with 363 vertex calls, a precision of 6.6%. Neither model is tradeable; both lose to a coin where nobody trained them. What survives is the method: a zone defined by two numbers takes 6–7% of events on any segment and exposes a gap that neither MAE (0.55 vs 0.48 for the constant) nor output spread could show. The next study keeps the target and the zone and changes the network. ================================================================================ # Six Networks Tried, the Winner Has 53 Parameters — Teaching a Model Where Price Sits in Its Leg URL: https://marketflowresear.ch/articles/six-networks-one-winner-with-53-parameters/ Published: 2026-09-30 · Series: The road to Bot 7 · Zigzag net > Correlations said the slow order book knows roughly where price sits inside its zigzag leg. So we trained networks to say it out loud: a number from −1 (at the low pivot) to +1 (at the high pivot), from four book features under thirteen averages. Six families on the same data, a time split with five walk-forward windows — and the linear model with 53 parameters won. On the final test it beats the constant for the first time (MAE 0.438 vs 0.446, sign 55.1%); on eleven fresh days outside the dataset, sign 60.7% on 44 legs. Small, consistent — and the reason is a loss that pays attention to the edges of the leg. ## ① A target that moves slowly, and a split that respects it The target is the **position of each event inside its zigzag leg**: an independent 0.8% zigzag on event prices, the leg rescaled by rank to [−1, +1] and smoothed with a 10-event EMA *on the leg* (so the pivots stay put). Switching from a 0.8% zigzag on smoothed price to this one raised the number of legs from 110 to **684** — and legs, not events, are the independent units here, so the error bar on a sign rate fell from 4.8 to 1.9 points. The inputs are four dimensionless book features (`balance`, `d_balance`, `vol_balance`, `price_balance`) each under 13 EMAs from 10 to 130 events: a 13 × 4 matrix per event, rescaled by quantiles fitted on train. The first finding was a trap. The target changes slowly, so neighbouring events of one leg are nearly identical. Under a shuffled split, simply copying the target of the nearest training event gives a test MAE of **0.052 and 96.04% sign accuracy** — with no model at all. So the split is by time: `train | val | test` in contiguous blocks with gaps cut at pivots (never closer than 130 events), repeated over **five walk-forward windows**, and test never takes part in any choice. ## ② Six families, same budget — the simplest wins Six model families were compared on identical data and budget, each with default settings — families, not tunings. The metric is the mean validation MAE over the five windows. The **linear model (53 parameters)** won with 0.4157; the MLP (5,505 parameters), GRU, transformer (26,017), CNN and dilated CNN all came in between 0.421 and 0.427. The gap between train and validation error grows with model size — a clean sign that the extra capacity learns the training weeks rather than the market. The rest of the standard procedure then tuned only the winner: a coarse grid on learning rate (best 0.0001, at the edge, so the neighbourhood widened), patience of the early stop (30 epochs), and a moving neighbourhood search over learning rate and two loss weights that closed after three rounds at **lr 0.0003, α 1, β 2**. The grid always kept α = 0 — plain MSE — as a check that the weighting earns its place. It did: 0.4131 against 0.4145. ## ③ Weight the edges of the leg — and the model generalises The weighted loss is `w = 1 + α·|y|^β`: an error at a pivot costs more than an error mid-leg. Under plain MSE almost all of the gradient came from the middle of the leg, where there is least signal; the weight moves attention to the edges, where there is some. On the final split (train Feb–May, val late May–June, test 29 June–16 August; 10,033 test events, 112 legs) the effect is not a bolder output — the spread only goes from 0.34 to 0.36 of the target's — but a **better** one. Test MAE **0.4381** against 0.4461 for the constant, R² **+0.0067** (plain MSE: −0.0519), Pearson **0.187** (MSE: 0.093), sign **55.05%** (MSE: 52.58%). Across the five walk-forward windows the sign rate is 55.12% ± 1.50, better than the constant in 5 of 5. We then tried five other ways to punish error. The three that force the output to have the target's spread (a spread penalty, post-calibration, a correlation loss) all make MAE worse and R² negative — calibration keeps Pearson at exactly 0.1873 while MAE gets 23% worse. **Stretching the output is not the same as being right.** Pseudo-Huber edged out the weighted MSE on all four test metrics (MAE 0.4355, sign 55.45%), but on validation the three point losses sit within 0.4% of each other — indistinguishable by the selection rule. ## ④ Eleven fresh days, and how much to believe it The saved model and scaler were then run on raw data *outside* the dataset — 14 August 14:00 to 25 August 2026, rebuilt through the same chain of classes. On **2,512 events and 44 legs**: MAE **0.387**, R² **0.100**, Pearson **0.344**, sign **60.71%**. Plain MSE on the same window: 59.63%, Pearson 0.279 — the weighted loss is better on all four numbers. How much to believe it is a question of legs, not events. Across all five walk-forward windows there are 295 independent legs: a standard error of 2.9 points, and the 55% sign rate sits **1.76 SE** above a coin. The fresh window alone is 1.43 SE. Neither number proves anything alone; what matters is that three independent looks — walk-forward, final test, fresh days — all land on the same side. The ceiling is not in the loss. Every point loss leaves the output at about a third of the target's spread, because the underlying correlation is about 0.25. The next studies in this series move the target instead: a 2.3% leg, and a loss that rewards landing in the pivot zone. ================================================================================ # Twelve Hours of Order-Book State and the Direction of a Move — From 0.16 to 0.42 URL: https://marketflowresear.ch/articles/twelve-hours-of-order-book-state-and-the-direction-of-a-move/ Published: 2026-09-30 · Series: The road to Bot 7 · Slow book state > Does the order book, averaged over about half a day, know which way the current move is going? We smoothed four book features with exponential averages on 52 horizons from 35 minutes to 58 hours and correlated them with the direction of 2.3% and 0.8% zigzag moves on 40,242 BTC events. The raw answer is weak (−0.16 at best). Three changes of question — a price feature instead of price, the position inside the leg instead of the direction, and a zigzag drawn on the same smoothing — lift the ceiling to 0.42. That is 17% of the variance, from a description that ignores the last hour entirely. ## ① The raw answer: weak, and pointing backwards The events are the same 210-second windows as everywhere in this series — **40,242 BTC events** from 14 February to 16 August 2026, laid out as one continuous timeline. Each is reduced to three normalised differences between the two sides of the book: `balance` (resistance versus support), `d_balance` (how fast that balance changes) and `vol_balance` (buy versus sell volume). Then each gets an exponential average over 200 events — about 11 hours 40 minutes — together with the price. The target is the direction of the zigzag move the event sits in: +1 up, −1 down, for two independent zigzags, 2.3% and 0.8%. No parameters, no randomness, no seed; the result is deterministic. The honest first answer: **there is a link, and it is weak.** The strongest is the book balance against the small zigzag: **−0.161** (Pearson; Spearman −0.146), about 2.6% of shared variance. The sign is negative — during a rise the averaged book leans toward support, during a fall toward resistance — and it holds on both zigzags and both metrics. On the big 2.3% zigzag everything is roughly half as strong. The price level itself says almost nothing (−0.02 to −0.04), which is what you would expect. ## ② A price feature beats the price The first change: instead of averaging the price, turn it into a feature built by the same rule as the others — the normalised difference between upward and downward movement inside each 14-second block, i.e. *how straight* the price travelled. All four series then live on the same [−1, 1] scale. We swept the averaging period over **52 values**, from 10 to 1,000 events (0.6 to 58.3 hours). The price feature reaches **+0.217** against the 0.8% zigzag at period 20 (about 1.2 hours) — where plain price managed −0.023. The change of balance mirrors it at **−0.231**. The mirror is not a coincidence. The pair `d_balance × price_balance` correlates at **−0.67 to −0.93** across the whole grid: the difference in how the two walls move is mostly the same information as the direction of price, with the opposite sign. None of the six feature pairs is close to independent (|r| from 0.24 to 0.93). Four series, fewer than four pieces of information — and the ceiling is still about ±0.23, some 5% of the variance. ## ③ Ask where, not which way — on a smoothed zigzag Two more changes of question moved the ceiling far more than any feature did. **Position instead of direction.** Every event gets its place inside its zigzag leg: −1 at the low pivot, +1 at the high pivot, proportional in between — and the feature is rescaled the same way over the same leg, so like is compared with like. On the small zigzag this gives the strongest numbers so far: price feature **+0.328**, change of balance **−0.338**, with peaks on long periods (450–1,000 events) rather than 10–20. The book holds "where are we in the leg" better than "where is the leg going". **A zigzag drawn on the same smoothing.** Instead of pivots on raw event prices, first smooth the price with the *same* EMA period as the features, then draw the zigzag. Now volume balance against the 2.3% direction goes from −0.049 to **−0.396**, and the best cell of the study appears: volume balance against the position in a 0.8% leg, period 380 events (≈ 22 hours), **−0.417** — about 17% of the variance against 5% before. Two signs flip in the process: book balance and its change run *against* small wiggles but *with* the smoothed trend (+0.24). We also tested three ways to rescale inside a leg (min-max, robust, quantile). They change the magnitude by 0.02–0.09 and **never flip a sign** — quantile wins on raw price, min-max on smoothed price, robust is weakest because a leg is a monotone move, not a cloud around a centre. ## ④ What 0.42 means — and what it does not The picture is consistent and it is useful: slow book state carries real information about the phase of a move, and it carries it best when the question is posed on the same time scale as the features. The volume balance is the most stable of the four: buying pressure runs *against* the rise, −0.30 to −0.40 on long periods, on every variant. Two limits keep this from being a trading rule. First, the target is a zigzag label, and a zigzag pivot is only confirmed after the move — the correlation describes a leg, it does not call it in advance. Second, a smoothed zigzag moves its pivots later still. This study measured *how much* the slow book knows about the leg; the next ones in this series try to turn that into a label a model can learn causally, event by event. ================================================================================ # Predicting the Next Phase of a Move From the Order Book — 832 Window Sizes, One Honest Ceiling URL: https://marketflowresear.ch/articles/predicting-the-next-phase-of-a-move-from-the-order-book/ Published: 2026-09-30 · Series: The road to Bot 7 · Next cohort > Every event of BTC's order book sits in one of four phases of a zigzag: rising, a pullback inside a rise, falling, or a pullback inside a fall. We asked a closed-form linear model to name the phase of the next event from the N events before it — and tried every N from 2 to 833. The signal is real from N = 2, peaks at 0.418 accuracy on about one zigzag leg of history against a 0.377 baseline, and is essentially binary: up or down, the pullbacks go unseen. The labels of the past alone would score 0.976. ## ① Four phases of a zigzag The labels come from two zigzags laid on the same price series: a big one with a 2.3% threshold and a nested one at 0.8%. Their pivots merge into a single timeline, and the stretch between two neighbouring pivots is a *segment*. Each 210-second event lies in exactly one segment and takes two labels from it: the direction of the big move it belongs to, and the direction of its own segment. The pair is its **cohort**. On the BTC training set (24,150 events, 14 February – 16 August 2026; 116 big pivots and 472 small ones) that gives **8,878 rising** events, **2,742 pullbacks inside a rise**, **9,123 falling** and **3,195 pullbacks inside a fall**; 212 events sit outside the zigzag. Pullbacks are a separate cohort on purpose: they occupy the same place in a move as trend segments but point the other way, and a bot that confuses the two gets shaken out of every trend. The labels are known only in hindsight — a zigzag pivot is confirmed by the move that follows it. That is why the forecast below never sees the labels of past events, only their order-book description. ## ② A closed-form model, 832 window sizes The forecaster is deliberately the simplest honest thing: each cohort is a Gaussian in the space of the window, with a shared covariance, and the decision is Bayes' rule — a **linear discriminant** computed from sums in closed form. No iterations, no seed, no tuning. Each event contributes two numbers (the mean over its 15 blocks of `balance` and `d_balance`), so a window of N events is 2N columns; the target event itself is never in its own window. Windows of neighbouring targets overlap, so a random split would leak. Instead the training set is cut into **five contiguous time blocks**; each block is predicted by a model trained on the other four, with a quarantine of **±833 events** around it so no training window touches a test window. Then the window grows: N from 2 to 833 in steps of one — **832 separate runs** on the same 23,194 targets. Against the baseline "always say falling" (0.3768 ± 0.0032), accuracy is **0.3971 at N = 2** (+6.4 standard errors), rises to a peak of **0.4182 at N = 203** (+13.0 SE) and falls back almost to the baseline beyond 600 events. The best window is about the length of one 2.3% leg; more distant history adds more noise than information. ## ③ Binary in practice — and the ceiling that labels would give Look at what the best model actually says. At N = 203 it names **55.2%** of rising events and **55.1%** of falling ones — and **0.1%** and **2.2%** of the two pullback cohorts. Pullbacks are a third the size of their trend cohorts, and the order-book window does not separate them, so the model simply stops naming them. Formally the four-cohort criterion passes (balanced accuracy 0.284–0.291 against 0.25 by chance); in practice the model splits the field into "up" and "down", and weakly. The gain is small: +2 points at N = 2, +4.1 at the best window. That is a feature, not a trading signal. The most useful number in the study is a different one. A "persistence oracle" — *the next event has the same cohort as the previous one* — scores **0.9757**. It cannot be traded, because the previous label is only known after the zigzag confirms it. But it shows where the structure lives: cohorts run in long stretches, and almost all the predictability is in the sequence of labels, not in 210·N seconds of book state. So the next step in this series is not a longer window. It is estimating the phase of the **current** event — where in its leg the market is right now. ================================================================================ # A Leg Is the Sum of Its Events — and Size Beats Count URL: https://marketflowresear.ch/articles/a-leg-is-the-sum-of-its-events-size-beats-count/ Published: 2026-09-30 · Series: The road to Bot 7 · Legs and events > We cut the price of six coins into 210-second events and into 2.3% zigzag legs, then asked the simplest question a direction model has to answer: how does a leg actually make its move? Over 712 legs and 409,998 events the answer is exact — the leg is the sum of its events (0.999 on clean legs) — and surprising: up legs are only 51.9% up-events. The move is carried by the size of events, not by how many point the right way. ## ① The map before the labels Every study in this series works on the same raw material: the Binance order book recorded every second — eight book features plus price — for six coins since February 2026. The unit of analysis is an **event**: 210 seconds of that stream, described by a *class*, a fixed recipe that compresses the window into a small matrix of numbers. The first thing we did was look before labelling. We projected the BTC training set — **24,150 events** from 14 February to 16 August 2026 — with UMAP, for every stored class of the dataset (from 3 to 90 numbers per event), each under three distance metrics, in 2D and in 3D. Sixty maps in total, all with the same seed (`n_neighbors 30`, `min_dist 0.1`), so they are directly comparable: the events are identical, only their description changes. What the maps show: **no islands.** The events form one continuous cloud — there is no ready-made category waiting to be named. But colour each point by the price change *during that same event* and the cloud is not uniform: rising events gather on one side, falling ones on the other. That is a description, not a forecast — the numbers and the price change come from the same 210 seconds. Price change per event runs from −1.13% to +2.66% with σ = 0.123%, so a single event is a very small step. The real question is how those small steps add up into a move — which is where the rest of this article goes. ## ② A leg is exactly the sum of its events The precise question was about **legs**: moves of at least 2.3% on a smoothed price (EMA-10 of event prices), between zigzag pivots. We used the full continuous series of all six coins — **712 legs** (355 up, 357 down), **409,998 events**, median 416 events per leg, median move 4.41%. First, a sanity check that turned into a result. The move of a leg correlates with the sum of its events' moves at **+0.949**; the sign matches on **99.3%** of legs, and on the 217 legs with no holes in the data the ratio is **0.999**. A leg is not "made of" its events in some loose sense — it *is* their sum. Whatever tells a leg's direction must be visible in the events. Then the useful part. The sum of event moves splits exactly into two terms in the same units: a **count** term (more events point the leg's way) and a **size** term (events pointing the leg's way are bigger). The size term carries **57%** of the move and matches the leg's direction on **93.5%** of legs; the count term carries 43% and matches on 86.9%. Correlation with the leg's move: +0.842 for size, +0.720 for count. ## ③ Why you cannot read direction from one event Here is the number that explains why direction is hard. Inside an up leg, **51.9%** of events are rising; inside a down leg, **46.7%**. That is the entire count advantage — about five percentage points, accumulated over hundreds of events. It is the same on every coin: 0.514–0.525 in up legs, 0.458–0.479 in down legs. The size effect is just as small per event and just as consistent. In an up leg, rising events average 0.1239% against 0.1059% for falling ones; in a down leg the mirror image, 0.1070% against 0.1236%. A skew of roughly 0.018% per event — tiny on one event, decisive over four hundred. Where the edge is strongest tells you where to look: **the first tenth of the leg**, right after the pivot — 0.548 rising in up legs against 0.428 in down legs, a 12-point gap against about 4 points in the middle. After that the edge is flat to the end. Practical consequence for any label or model: measure **the skew of event sizes over a window of tens of events**, not the sign of the last event. ## ④ Legs that move against their own majority If the edge is that thin, some legs must lack it. We took them apart. **87 legs (12.2%)** made their move while having *fewer* events pointing their way. They are not glitches: they win on size, and they win in jumps. Their size skew is 0.193 against 0.111 for an ordinary leg, their ten biggest events deliver **62.1%** of the net move (against 40.4%), and their top 10% of events deliver **106.3%** — more than the whole move, meaning the other 90% of events pull backwards. They are also longer: 523 events median against 392. **46 legs (6.5%)** had the count but not the size: events against the leg were bigger. These are the weakest legs — median move 2.96% against 4.53%, 272 events against 438 — built from many small steps, with the top ten events giving only 12.7% of the move. Legs where *both* count and size go against the leg do not exist in the market. There are exactly three, and all three sit on holes in the data (median gap 59.4 hours). That is a data-quality filter, not a pattern. And in every group the move gathers at the **edges** of the leg — the first and last tenth — and least in the middle. The edges of a leg are where the next studies in this series go looking. ================================================================================ # Line 7: The Best of All Our Bots — Live Trading Report, Every Trade URL: https://marketflowresear.ch/articles/line-7-live-trading-report/ Published: 2026-10-28 · Series: Live bots — every result · Live report · Line 7 > We have built and tested more than a dozen trading bots on the research published here. Line 7 is the only one ahead of buy & hold in live trading: from 5 October to 28 October 2026 its paper account made +5.44% after costs while BTC fell 5.29% — 6 trades, 5 take-profits. Real positions on the exchange: +1.39 USDT. Six trades are not a track record; this report lists every one of them and is updated as trades close. Research, not financial advice. ## ① All our bots, one scoreboard | Bot | How it was tested | Trades | Result | Buy & hold, same days | |---|---|---|---|---| | Bot 1 "Battle" | historical run on the full dataset | 211 | −44.0% | −16.0% | | Bot 2 | historical run; zero trades in its live week, 8–14 Jul | 72 | +55.8% (historical only) | — | | Bot 4 | live paper trading, six coins, 9 Jul – 6 Sep | 169 | −3.45% | +32.0% | | Bot 6 · line 61 | live paper trading, six coins, 75 days to 30 Sep | 32 | −10.70% | +35.3% | | Bot 6 · line 60 | live paper trading, six coins, 15 Jul – 5 Oct | 39 | +8.66% | +22.8% | | Bot 7.0 | live, BTC, 30 Sep – 5 Oct | 1 | +1.17% | +2.81% | | **Bot 7 · Line 7** | **live, BTC, 5 Oct – 28 Oct, paper + real exchange** | **6** | **+5.44%** | **−5.29%** | Every bot in this table was built from the research on this site. Of those that traded live, every one except Line 7 ended behind simply buying and holding over the same days — including the two that made money. Line 7 is the only bot ahead of buy & hold in live trading: **+5.44% against −5.29%**. Two honest caveats come with that sentence. Its live record is 23 days and 6 trades. And it was earned in a falling market, where being out of the market already helps. But Line 7 did not just lose less than the market — it made money while BTC fell: 5 of 6 trades closed at take-profit. Smaller experiments — lines 5A, 5B, 5X_20, 50, 62 and two clones of line 60 — were retired after a handful of trades or after failing validation, so they are not in the table. ## ② How Line 7 decides Every 10 minutes Line 7 looks back over the last 160 hours of second-by-second Binance order book for BTC — resting liquidity on both sides, liquidity added and pulled, buy and sell flow — folds it into a canvas of 1,100 records of 100 seconds with 8 features each, and hands the canvas to two small transformers. One says how likely it is that this moment sits in a 2.3% bottom zone, the other — in a 2.3% top zone. - **Entry:** each probability is summed over its own window — 340 minutes for buys, 30 for sells — and a trade opens when the sum crosses its threshold (2.72 and 1.74). - **Exit:** take-profit 1.9%, stop 2.5%, or a signal from the other side closes the position. - **Discipline:** one position at a time, one trade per 2.3% leg. The pair of networks was not picked for the most money on validation: it was picked for behaving the same on three separate stretches of data. The whole path — how the networks were trained, what each version made on every stretch — is in [Bot 7: from an order-book canvas to live trading](/articles/bot-7-from-an-order-book-canvas-to-live-trading-every-result-every-trade/). ## ③ Every trade | # | Version | Side | Entry (UTC) | Exit (UTC) | Exit by | Result after costs | |---|---|---|---|---|---|---| | 1 | 7.0 | long | 1 Oct 14:40 at 84,189.26 | 2 Oct 03:01 at 85,398.81 | take-profit | **+1.17%** | | 2 | 7 | long | 7 Oct 14:40 at 83,042.99 | 8 Oct 17:00 at 80,962.59 | stop | **−2.76%** | | 3 | 7 | long | 8 Oct 17:00 at 80,962.59 | 9 Oct 04:20 at 82,515.32 | take-profit | **+1.65%** | | 4 | 7 | long | 12 Oct 23:10 at 82,179.65 | 13 Oct 06:50 at 83,776.24 | take-profit | **+1.68%** | | 5 | 7 | long | 14 Oct 15:30 at 81,971.00 | 20 Oct 15:10 at 83,040.01 | opposite signal | **+1.04%** | | 6 | 7 | short | 20 Oct 15:10 at 83,040.01 | 22 Oct 16:50 at 81,141.88 | take-profit | **+2.03%** | | 7 | 7 | long | 24 Oct 16:50 at 80,044.87 | 28 Oct 08:40 at 81,665.78 | take-profit | **+1.76%** | Costs are inside every number: 0.10% exchange fee and 0.02–0.03% slippage per side. Trades are booked at the close of the 10-minute decision step, the way the bot itself books them. No position is open at the time of this update. ## ④ The paper account against buy & hold The paper account of the current version started with $10,000 on 5 Oct 22:00 UTC. On 28 October 2026, 11:50 UTC it holds **$10,543.75** (+5.44%). Buying BTC at the first step and holding it to the last would have given **−5.29%**. With the cheaper costs used in our research runs (0.05% fee + 0.02% slippage) the same trades give $10,619.60. Before it, version 7.0 (buys only) traded from 30 Sep 20:00 to 5 Oct 21:50 UTC: one trade, one take-profit, +1.17% while BTC rose 2.81%. ## ⑤ Real money on the exchange Every signal is also sent to a real **CEX.IO margin account: a $100 position at ×4 leverage**. Closed so far: | Position | Side | Entry | Exit | Net after fees and rollover | |---|---|---|---|---| | #129035 | long | 83,067.00 | 80,893.60 | **−2.84 USDT** | | #129249 | long | 80,900.10 | 82,511.00 | **+1.78 USDT** | | #130929 | short | 82,464.00 | 81,476.00 | **+0.95 USDT** | | #131441 | long | 80,133.70 | 81,589.00 | **+1.51 USDT** | Net on the exchange: **+1.39 USDT**. The exchange side differs from the paper account for reasons we publish as they happened. Position #129249 opened on 8 Oct without the bot's exit orders because of an error in the bot's order code; its owner moved the take-profit by hand and closed it on 20 Oct, so trades 4 and 5 of the table above never reached the exchange. The short #130929 was sent after that pause and entered 0.69% worse than the model's price, which is why it made +0.95 USDT where the model booked +2.03%. Fills otherwise land within 0.1% of the model's prices. ## ⑥ What six trades can and cannot tell A winning trade has paid about +1.63% after costs and the stop −2.76%, so the bot needs to win about 63% of its trades just to stand still. A bot with exactly that break-even win rate and no edge at all would still win 5 or more of 6 trades in about **28% of cases** — roughly one time in 4. Six trades cannot rule luck out. What they show is narrower and still useful: the signal has not fallen apart outside the data it was chosen on, and the gap to buy & hold so far points the right way. That is why this page is a live report rather than a claim. Every new trade is added, losing ones included, and the scoreboard above is recomputed — if Line 7 stops being ahead, this page will say so. **Research, not financial advice.** Nothing here is a recommendation to buy, sell or copy these trades. Past results — especially six of them — say little about the next trade. ================================================================================ # Bot 7 — From an Order-Book Canvas to Live Trading: Every Stretch, Every Result, Every Real Trade URL: https://marketflowresear.ch/articles/bot-7-from-an-order-book-canvas-to-live-trading-every-result-every-trade/ Published: 2026-10-09 · Series: Live bots — every result · Bot 7 overview > Bot 7 is the end of a long research line: a transformer reads 30 hours of BTC order book as one canvas and says how likely it is that this moment sits in a 2.3% bottom — or, in its second version, a 2.3% top. This article puts the whole path in one place: how the networks were trained, what each version made on training-period weeks it was not fitted on, on validation, on days nobody had looked at, and since it went live. All live trades so far are listed at the end, model and exchange side by side. As of 9 October 2026 08:20 UTC the record is three closed trades: two take-profits and one stop. ## ① How bot 7 was trained **Input.** Every 10 minutes the bot takes the last **160 hours** of second-by-second Binance order-book data (resting liquidity on both sides, liquidity added and pulled, buy and sell flow), folds it into **1,100 records of 100 seconds** and 8 features each, and gives the canvas to a small transformer. The output is one number: the probability that *now* is inside a 2.3% zigzag pivot zone. The zone is the honest label: a stretch of time around a bottom (or top) whose legs last at least 7 hours, within 10% of the leg's move from the extreme. **Training.** BTC only. Networks learn on **21 Feb – 30 Jun 2026** (15,878 steps), a 200-hour gap follows, and **8 Jul – 12 Aug** (4,445 steps) is held out to choose the epoch. Eighteen runs per side differ only in the loss function. **15 Aug – 21 Sep** (5,265 steps) is validation: here the signal is turned into trades — the probability is summed over a window W, the bot acts when the sum reaches θ — and here W, θ and the networks were chosen. **Two versions.** *Bot 7.0* buys only: `BUY_pos` epoch 9, W 180 minutes, θ 11.74, take-profit 1.9% above the lowest price after entry, stop 2%, a filter for repeat signals and rule 7.1. *Bot 7* trades both sides on one account: `BUY_l3` epoch 3 (W 340 min, θ 2.72) and `SELL_l2` epoch 17 (W 30 min, θ 1.74), one trade per 2.3% leg, take-profit 1.9%, stop 2.5%, a signal from the other side closes the trade. The pair was chosen not for money but for behaving the same on three stretches. ## ② Results on every stretch — against buy & hold All historical runs start from $1000, put the whole account into each trade, use no leverage and pay 0.05% fee plus 0.02% slippage per side. **Held-out training weeks, 8 Jul – 12 Aug** (bot 7): **$1086.70** against **$1022.67** for buying and holding — the only stretch where the bot clearly wins, in a month BTC rose 2.4%. **Validation, 15 Aug – 21 Sep**: bot 7.0 **$1100.85** with nine trades, all take-profit; bot 7 **$1147.38**; buy & hold **$1289.36**. BTC rose about 29% and a bot that is out of the market much of the time cannot keep up. Every parameter was chosen here, so these are the most flattering numbers. **Unseen days**: bot 7.0 on 21–30 Sep **$1032.92** (three trades, three take-profits) against **$1035.51**; bot 7 on 21 Sep – 5 Oct **$1059.30** against **$1064.02**. The pattern is consistent and not exciting: positive everywhere, roughly level with the market when the market is calm, far behind it in a strong rally. Earlier articles of this series give each stretch in full. ## ③ Live since 30 September — every trade so far The bot runs on the data collector's live feed, a decision every 10 minutes. The model's trades are booked on paper from $10,000 at the close of the decision step, with exchange-level costs (0.10% fee + 0.02–0.03% slippage per side). In parallel each trade is sent to a real **CEX.IO margin account: a $100 position at ×4 leverage**. Bot 7.0 ran from **30 Sep 20:00 to 5 Oct 21:50 UTC**; bot 7 replaced it at **5 Oct 22:00 UTC**. All trades as of 9 Oct 2026 08:20 UTC (model, paper): - **7.0 · long** · in 1 Oct 14:40 at 84,189.26 → out 2 Oct 03:01 at 85,398.81 · **take-profit · +1.17%** - **7 · long** · in 7 Oct 14:40 at 83,042.99 → out 8 Oct 17:00 at 80,962.59 · **stop · −2.76%** - **7 · long** · in 8 Oct 17:00 at 80,962.59 → out 9 Oct 04:20 at 82,515.32 · **take-profit · +1.65%** Paper account: bot 7.0 **$10,000 → $10,117.31** while BTC rose 2.81% over its days; bot 7 **$10,000 → $9,884.89** while BTC fell 3.84% over its days. Real exchange positions ($100, ×4): - **#129035 · long** · in 83,067.00 → out 80,893.60 (stop) · **−2.84 USDT** after 0.23 USDT fees and rollover — the model expected −2.76%, the exchange gave −2.84% - **#129249 · long** · opened 8 Oct 17:00 UTC at 80,900.1 · **still open** — the account owner moved its take-profit by hand to 85,000 (stop 78,938.2), so the model's take-profit at 82,500.88 was booked on paper but not on the exchange - Bot 7.0's single trade never reached the exchange: the order failed on a missing component of the order client, and it was fixed afterwards Three trades are not a track record, and this list is not a claim of an edge. It is published so the result can be checked against what the research promised: so far a take-profit is about 1.2–1.7% after costs and a stop about −2.8%, so the bot needs roughly two wins per loss just to stand still. The list will be updated as trades close. Research, not financial advice. ================================================================================ # Bot 6, Line 61: Nine Trades, Eight Winners, and Why We Are Not Celebrating URL: https://marketflowresear.ch/articles/bot-6-line-61-nine-trades-eight-winners/ Published: 2026-08-17 · Series: Live bots — every result · Line 61 live > Line 61 of Bot 6 holds one position at a time and has been live since 17 July 2026: 31 days, 9 closed trades, +11.81 USD on a 100 USD slot, win rate 89%. Its entry gate is agreement between two independent models plus a context check; its exits are a 2% target, a 4% stop and a hard 72-hour clock. This is the complete record, including the comparison with its twin line running the identical recipe — which is the part that keeps us honest. ## ① One trade at a time: how line 61 works Line 61 is one instance of Bot 6 — a bot that holds **one position at a time, across all six coins**, with a single slot of 100 USD. It has been running on live data since 17 July 2026, on paper, with a fee of 0.15% per action. Its entry rule is a gate made of agreement rather than of thresholds. An ensemble of models scores every coin; a trade is allowed only when the ensemble's confidence clears τA = 0.618, a second, independent model agrees on the same side, and a context check confirms the wider market state. If two of the three disagree, there is no trade — and there is no fallback, no "trade the best of a bad lot". The bot simply waits. Exits are equally plain: take profit 2%, stop loss 4%, and a hard **72-hour timeout** that closes anything still open at whatever price is there. That timeout is the part to watch in the results below. The recipe was chosen on a grid of 30 settings, on training episodes only, with one rule that threw out otherwise attractive candidates: a setting had to produce a signal in at least 60% of episodes. A gate that opens twice a year will show a wonderful win rate and teach you nothing. On the validation period the chosen recipe made +7.88 USD over 8 trades, with a median wait of 12.8 hours before a signal and 12.8 hours in the position. There is one more moving part. After **every closed trade**, a challenger is retrained on the freshest data and compared with the running version; the better one keeps the line. Line 61 is on version 4 after 10 such rounds. ## ② 31 days live: the numbers As of **2026-08-17**, after 31 days live: | measure | value | |---|---| | closed trades | 9 | | net result | **+11.81 USD** (+11.81% of 100 USD) | | win rate | 88.9% | | average trade | +1.312% · median +1.810% | | median holding | 58.6 h | | how they ended | take profit — 7, 72 h timeout — 2 | | best / worst | DOGE +2.12% / SOL -1.86% | | buy & hold, same coins and days | +0.09% on average (BNB +7.3%, BTC +1.8%, DOGE -2.1%, SOL +1.5%, XRP -7.9%) | Open at the time of writing: BTC long +1.98% after 31 h — +1.83 USD unrealised in total. One trade at a time over 31 days means roughly one closed position every 3.5 days — and that number is the most informative one in the table. This bot spends the overwhelming majority of its life flat, waiting for its three conditions to line up. Every result it produces has to be read with that in mind: with 9 closed trades, a single outcome moves the win rate by 11 percentage points. The exits column is where the mechanism shows through. take profit — 7, 72 h timeout — 2 — and the split between "hit the target" and "ran out of time" says more about the bot than the profit does. A position closed by the clock is one where the entry was not wrong enough to hit the stop and not right enough to hit the target within three days. ## ③ Nine trades, eight winners, and why that is not proof 7 of line 61's 9 closed trades hit their take profit, the win rate is 89%, and the line is +11.81 USD ahead on a 100 USD slot. This is the best live result in the project so far, and this section exists to argue against reading too much into it. Start with the sample. 9 trades. If this gate were a coin flip, the chance of seeing 8 or more winners out of 9 is 0.020 — about one run in 51. Unlikely, then, but nowhere near proof: we run several bot lines, and one of several coin flips landing well is the ordinary case, not the remarkable one. Then look at its twin. Line 60 runs **the same recipe, the same gate, the same six coins**, launched two days earlier, and closed 9 trades for +0.68 USD at a 44% win rate. Nothing distinguishes the two systems except which entries each happened to catch. If line 61's numbers proved the method works, line 60's would prove it does not — and both cannot be true. What *is* solid in this line has nothing to do with the profit. The exits: a median holding of 58.6 hours, with take profits dominating the timeouts, means the gate tends to fire in front of moves that resolve inside the bot's three-day window. That is a statement about the entry mechanism, it is consistent across the trades, and it does not depend on the size of the wins. Buy & hold over the same days and coins: +0.09% on average (BNB +7.3%, BTC +1.8%, DOGE -2.1%, SOL +1.5%, XRP -7.9%). So the line is ahead of holding, by a margin that a single bad trade would erase. It keeps running unchanged, it retrains a challenger after every close, and its balance goes out in a daily report — including the days it gives some of this back. ================================================================================ # Bot 6, Line 60: A Bot That Mostly Waits — and What the Clock Costs It URL: https://marketflowresear.ch/articles/bot-6-line-60-a-bot-that-mostly-waits/ Published: 2026-08-17 · Series: Live bots — every result · Line 60 live > Line 60 of Bot 6 holds one position at a time and has been live since 15 July 2026: 33 days, 9 closed trades, +0.68 USD on a 100 USD slot, win rate 44%. Its entry gate is agreement between two independent models plus a context check; its exits are a 2% target, a 4% stop and a hard 72-hour clock. This is the complete record, including the comparison with its twin line running the identical recipe — which is the part that keeps us honest. ## ① One trade at a time: how line 60 works Line 60 is one instance of Bot 6 — a bot that holds **one position at a time, across all six coins**, with a single slot of 100 USD. It has been running on live data since 15 July 2026, on paper, with a fee of 0.15% per action. Its entry rule is a gate made of agreement rather than of thresholds. An ensemble of models scores every coin; a trade is allowed only when the ensemble's confidence clears τA = 0.618, a second, independent model agrees on the same side, and a context check confirms the wider market state. If two of the three disagree, there is no trade — and there is no fallback, no "trade the best of a bad lot". The bot simply waits. Exits are equally plain: take profit 2%, stop loss 4%, and a hard **72-hour timeout** that closes anything still open at whatever price is there. That timeout is the part to watch in the results below. The recipe was chosen on a grid of 30 settings, on training episodes only, with one rule that threw out otherwise attractive candidates: a setting had to produce a signal in at least 60% of episodes. A gate that opens twice a year will show a wonderful win rate and teach you nothing. On the validation period the chosen recipe made +7.88 USD over 8 trades, with a median wait of 12.8 hours before a signal and 12.8 hours in the position. There is one more moving part. After **every closed trade**, a challenger is retrained on the freshest data and compared with the running version; the better one keeps the line. Line 60 is on version 1 after 8 such rounds. ## ② 33 days live: the numbers As of **2026-08-17**, after 33 days live: | measure | value | |---|---| | closed trades | 9 | | net result | **+0.68 USD** (+0.68% of 100 USD) | | win rate | 44.4% | | average trade | +0.076% · median -0.580% | | median holding | 72.0 h | | how they ended | take profit — 2, 72 h timeout — 7 | | best / worst | ETH +2.40% / BTC -2.36% | | buy & hold, same coins and days | -2.09% on average (BNB +4.3%, BTC -1.2%, ETH -1.2%, XRP -10.3%) | Open at the time of writing: ETH long +1.50% after 40 h — +1.35 USD unrealised in total. One trade at a time over 33 days means roughly one closed position every 3.7 days — and that number is the most informative one in the table. This bot spends the overwhelming majority of its life flat, waiting for its three conditions to line up. Every result it produces has to be read with that in mind: with 9 closed trades, a single outcome moves the win rate by 11 percentage points. The exits column is where the mechanism shows through. take profit — 2, 72 h timeout — 7 — and the split between "hit the target" and "ran out of time" says more about the bot than the profit does. A position closed by the clock is one where the entry was not wrong enough to hit the stop and not right enough to hit the target within three days. ## ③ What the clock costs it Line 60's defining number is not its profit — it is that **7 of its 9 closed trades ended on the 72-hour clock**, not at a target or a stop. The bot was right that something was happening; it was wrong, or too early, about when. That is a specific and fixable failure, and it is worth separating from the general "the strategy does not work". A timeout exit means the entry gate opened, the position went nowhere decisive for three days, and the bot took whatever was on the table — on this line, a median holding of 72.0 hours, which is the timeout itself. The move the model saw either arrived later, or was smaller than 0.08% and never reached the 2% target. The comparison that makes this concrete is line 61 — the same recipe, the same gate, the same six coins, launched two days apart. It closed 9 trades in 31 days for +11.81 USD at a 89% win rate, and its exits are dominated by take profits rather than timeouts. Two identical systems, one month each, 11.13 USD apart. We are not going to explain that gap with a story about market regimes. With 9 and 9 trades, the difference is inside the range that pure chance produces, and pretending otherwise is how people end up "improving" a system into overfitting. What the pair genuinely tells us is something narrower and more useful: **the same gate produces very different outcomes depending on which entries it happens to catch**, so the next piece of work is not a better gate, it is a better exit — one that reads the state of the move instead of counting hours. Buy & hold over the same days on the coins it traded: -2.09% on average (BNB +4.3%, BTC -1.2%, ETH -1.2%, XRP -10.3%). Line 60 finished +0.68 USD against that. Both numbers are small, both are honest, and both will be republished daily as they change. ================================================================================ # Bot 4: What Forty Days of Live Paper Trading Actually Look Like URL: https://marketflowresear.ch/articles/bot-4-forty-days-of-live-paper-trading/ Published: 2026-08-17 · Series: Live bots — every result · Bot 4 live > Bot 4 has been trading live on paper since 09 July 2026 — 40 days, 49 closed trades, +29.53 USD on 600 USD of capital, a 80% win rate, against +1.49% on average for buying and holding the same coins. This is the full record: the rules it never deviates from, every closed trade, the open positions right now, and the hourly referee that can hand the account to a freshly trained challenger — which has happened 4 times so far. ## ① The rules it has been playing by, unchanged Bot 4 has been running on live market data since **09 July 2026** — no breaks, no manual entries, no discretion. It trades on paper: every fill is simulated at the price its own data feed sees, with a fee of 0.15% charged on both the entry and the exit. That is the honest way to describe it, and it is the first thing anyone reading a results table should know. The rules it plays by have not changed since it was launched: - **six coins in parallel**, each with its own slot of 100 USD (600 USD of capital in total), never more than one position per coin; - **entry** only when four gates open at once — probability ≥ 0.55, expected value ≥ 0.002, both holding for 2 consecutive bars, plus an optional volatility floor the grid search left switched off; - **exit** at take profit 2% or stop loss 4%, or when the 48-hour episode ends — and at the end of an episode the bot stays in whatever it was in, rather than forcing a sale at a bad moment; - **at most 12 entries a day**, the house limit; - **entries pause automatically** when the data feed is thin or lagging by more than 15 minutes, while exits keep working — a stop must never depend on a healthy feed. The take profit is deliberately smaller than the stop loss. That is a standing rule here, not the output of an optimiser: the median 48-hour swing on these coins is 5.26%, so a 2% target is reachable often, while a 4% stop is far enough away that ordinary noise does not touch it. The bot wins small and often, and loses rarely and larger — which is exactly what the numbers below show. ## ② 40 days live: the numbers As of **2026-08-17**, after 40 days live: | measure | value | |---|---| | closed trades | 49 | | net result | **+29.53 USD** (+4.92% of 600 USD) | | win rate | 79.6% | | average trade | +0.603% · median +1.770% | | median holding | 46.2 h | | how they ended | stop loss — 10, take profit — 39 | | best / worst | SOL +3.03% / ETH -4.86% | | buy & hold, same days | +1.49% on average (BTC +3.7%, ETH +10.3%, SOL -1.6%, BNB +6.9%, XRP -7.9%, DOGE -2.6%) | Open at the time of writing: DOGE long +1.38% after 20 h; BNB long -0.22% after 98 h; SOL long +0.41% after 113 h; XRP long -1.38% after 144 h; ETH long -0.20% after 247 h; BTC long -0.16% after 311 h — -1.07 USD unrealised in total. Counting those open positions at their current price, the running score is +28.46 USD. Two readings of the same table, and both are true. The favourable one: the bot is ahead of buying and holding the same six coins over the same days, with a win rate near 80%, and it got there by taking small profits — the exits are dominated by take profits, not by lucky outliers. The careful one, which we owe the reader. 49 trades is a small sample, and the distribution here is asymmetric by design: many small wins, few larger losses. Before this bot went live, the same configuration was tested offline across three random seeds and averaged -19.7 USD, spread from -53.2 to +8.8, against buy & hold at -18.3 — that is, the offline verdict was "no better than holding, with a wide spread". The live run is currently at the good end of that spread. Nothing in the last 40 days proves the offline test wrong; it is simply too early, and we will keep publishing the number either way. ## ③ Champion versus challenger, refereed hourly The interesting part of Bot 4 is not the model — it is that the model is replaceable while running. Two copies trade side by side on the same live data: the **champion**, whose numbers are above, and a **challenger** trained on fresher data with a different take-profit/stop-loss geometry. A referee process compares them every hour on a single number: net result plus the value of everything still open. The rule is deliberately hard to game: *control passes to the challenger only if its score beats the champion's by more than 1 USD, and only after it has been trading for at least 48 hours*. The margin stops a coin flip from taking over the account, and the 48-hour minimum stops a challenger that got lucky in its first hour. Since launch: **17 challenger rounds, 4 handovers of control**, 500 recorded comparisons. Each round trains a new challenger on fresh data with the next geometry in the rotation — TP1.5/SL4.5, TP2/SL4, TP2/SL6, TP3/SL3.75, TP3/SL4.5, TP3/SL9 — and the loser is archived rather than deleted, so every version that ever ran can still be inspected. The current challenger has been live for 6 days with geometry TP3/SL9: 2 closed trades, +5.46 USD, win rate 100%, and 6 positions open, worth +6.98 USD unrealised. Its running score is +12.44 USD against the champion's +28.46. Why build it this way at all? Because the honest conclusion of every offline test we have run is that the difference between two decent configurations is smaller than the noise between two random samples of days. If you cannot tell which is better on a backtest, the only remaining method is to let both trade the real feed and give control to whichever survives — slowly, with a margin, and in public. That is the whole design: not a bot that is right, but a bot that can be replaced without anyone touching it. ================================================================================ # Gates: The Part of a Trading Bot That Decides Not to Trade URL: https://marketflowresear.ch/articles/gates-the-part-of-a-bot-that-decides-not-to-trade/ Published: 2026-08-17 · Series: Live bots — every result · Gates > A trading bot's model produces a number; its gate decides whether that number is worth a fee. This article measures what gates actually cost. Demanding a signal persist two bars instead of one raises precision from 0.209 to 0.238 and throws away 25% of the opportunities. Bot 4 stacks four gates and still lands inside the noise across random seeds. Bot 6 gates on agreement between two models — and two live lines running that identical gate for a month finished +11.81 and +0.68 USD apart. Gates buy precision with coverage; nothing here is free. ## ① A gate buys precision with coverage Every trading bot has two halves, and only one of them gets written about. The first half is the model: it looks at the market and produces a number. The second half is the **gate** — the rule that turns that number into "act" or, far more often, "do nothing". In our systems the gate is where most of the design work goes, because a raw model signal fires constantly and every firing costs a fee. The cleanest measurement of what a gate does comes from our zone-finding line, where a model marks the places a perfect trader would use. Take the same model and put four different gates behind it: | gate | zones still covered | precision of a signal run | combined train score | |---|---|---|---| | threshold only (τ = 0.87) | 0.745 | 0.209 | 0.2901 | | + must persist 2 bars | 0.560 | 0.238 | 0.2598 | | + must persist 3 bars | 0.399 | 0.239 | 0.2144 | | + volatility floor (q30) | 0.721 | 0.215 | 0.2678 | Read the first two columns as a single trade. Demanding that a signal survive two bars instead of one raises precision from 0.209 to 0.238 — about 14% better — and costs 25% of the opportunities. Going to three bars costs another 29% and buys almost nothing: precision 0.239 against 0.238. The volatility floor is the gentlest of the four and moves both numbers least. So the honest description of a gate is not "it makes the signal better". **A gate buys precision with coverage**, at a rate the data sets, and past a point the rate goes bad. The combined score in the last column — which weighs both — peaks at the plainest gate of all and falls with every addition. That is the trap this whole article is about: gates feel like improvements, and each one has to be paid for in trades you will never take. ## ② Bot 4: four gates in a stack Bot 4 is where this gets concrete. Its entry rule is a stack of four independent gates, and a trade happens only if **all** of them open: 1. **probability** — the classifier's chance of the move must clear π = 0.55; 2. **expected value** — the EV model must clear 0.002, so a likely move that is too small to pay the fee is refused; 3. **persistence** — the first two must hold for 2 consecutive bars, which is the same persistence gate as in the table above; 4. **volatility** — an optional floor on predicted volatility, which the grid search left switched off (None), because on our data it removed more good trades than bad ones. Every threshold is picked on the training episodes only. The geometry — take profit 2% against stop loss 4% — comes from the same training data, guided by a fixed house rule: the take profit is always *smaller* than the stop. The reasoning is the swing statistics, not taste: the median 48-hour swing is 5.26%, and a 2% target is reached from 33.5% of training bars. What loosening a gate does, measured on episodes the bot never saw: | version | gates | trades | win rate | take-profit exits | net on unseen episodes | |---|---|---|---|---|---| | 4.0, long only | persist 1, EV ≥ 0.004 | 28 | 50.0% | 42.9% | -6.88 USD | | 4.1, long + short | persist 2, EV ≥ 0.002 | 75 | 62.7% | 48.0% | +8.85 USD | Loosening EV while tightening persistence — and allowing shorts — nearly tripled the number of trades and turned -6.88 into +8.85 USD. It would be easy to stop here and call it a win. We do not, for one reason: across three random seeds the same configuration averages -19.7 USD with a spread from -53.2 to +8.8, against buy & hold at -18.3. The gate settings are inside the noise of which episodes you happened to test on. The strongest evidence for that caution is the geometry grid. Twelve take-profit/stop-loss pairs, each scored on training episodes and on held-out ones. The correlation between the two columns is **ρ = -0.67** — negative. Choosing the geometry that looked best in training was, on this data, slightly worse than choosing at random. That is not an argument against gates; it is an argument against believing the number you tuned them on. ## ③ Bot 6: the gate is agreement Bot 6 uses a different kind of gate, and it is our favourite one because it cannot be tuned into a corner: **agreement**. Two independent models look at the same market. The trade happens only when both say the same thing, the ensemble's confidence clears τA = 0.618, and a context check confirms the wider state. There is no threshold on "how strong" beyond that — the gate is a vote, not a dial. The grid that chose it had 30 settings and one hard floor: any candidate that produced a signal in fewer than 60% of episodes was rejected outright, however profitable it looked. A gate that almost never opens will show a beautiful win rate on the two trades it allows, and that is exactly the way to fool yourself. Chosen on training data: **+55.44 USD over 48 trades, win rate 85%**, a signal in 75% of episodes, median wait 9.4 h and median holding 12.1 h. On the validation period it never saw: **+7.88 USD over 8 trades, win rate 88%**, signal in 80% of episodes. The cycle is roughly 22 hours from "start looking" to "position closed" — this is a gate that spends most of its life shut. Then it went live, twice, with the same recipe on two independent lines. As of 2026-08-17: | line | days live | closed trades | net | win rate | how they ended | |---|---|---|---|---|---| | 60 | 33 | 9 | +0.68 USD | 44% | 7 of 9 by the 72-hour timeout | | 61 | 31 | 9 | +11.81 USD | 89% | 7 of 9 hit take profit | Same gate, same thresholds, same six coins, one month each — and one line makes +11.81 USD while the other makes +0.68. We are not going to tell you the second one is better tuned. With nine trades apiece, the honest reading is that this is what nine samples look like, and the useful signal is in the last column rather than the money column: on line 60 the position is usually closed by the clock, not by the target. A gate that opens on agreement can be right about "something is coming" and still be attached to a move that takes longer than the bot is allowed to wait. That is the working conclusion of everything above. The gate is not the part that finds money; it is the part that decides how often you are allowed to be wrong. Ours are chosen on data the bot never sees afterwards, they are kept as blunt as possible, and every one of them is measured in trades refused — because that is the price, and the price is always paid. ================================================================================ # Typhoon+: A Signal That Finds the Perfect Trader's Zones — and Still Loses Money URL: https://marketflowresear.ch/articles/typhoon-plus-a-signal-that-finds-the-zones-and-still-loses-money/ Published: 2026-08-17 · Series: Live bots — every result · Typhoon+ > We drew the zones a perfect trader would use — 0.9% zigzag turns, a 0.15% band around each one — and found that the price sits inside them barely 3% of the time. A single gradient-boosting model, pooled over six coins, then finds 74% of those zones on days it never saw. It also fires false 86% of the time, leans mostly on price geometry rather than the order book, and loses 122% when traded plainly against 93% for buy & hold. This is the article about a signal that finds the right places and still cannot pay the fee. ## ① The zones a perfect trader would use Start from the answer instead of the model. If a trader knew the future, where exactly would they act? Not everywhere — a perfect trader touches the market only at turns, and spends the rest of the time doing nothing. So we drew those places first and only then asked whether the order book can see them. A **zone** is built in two steps on 60-second bars. First a zigzag with a 0.9% threshold marks every turn where the price reversed by at least that much. Then, around each turn, we take the continuous stretch of bars whose price stays within 0.15% of the extreme — that stretch is the zone, the window inside which acting is as good as acting exactly at the turn. Neighbouring zones are kept at least 0.6% apart in price, so two zones can never be the same event counted twice. The result is the first honest number of this line: **5,326 zones across six coins**, between 4.0 (BNB) and 8.7 (SOL) per day, and the price sits inside a zone only **2.6 – 3.3% of the time**. Roughly 97% of all minutes are, for a perfect trader, waiting. That waiting has a price tag. On BTC alone the perfect trader takes 196 trades over the validation period — 4.47 a day — on moves averaging 2.00%, netting 1.436% per trade after fees, or **6.42% a day**. Across six coins the perfect trader finishes the same period at **2448%**. That is the ceiling this line is measured against — not a benchmark we expect to reach, but the yardstick that turns "the signal looks good" into a number. ## ② One model, six coins, four wrong calls in five One model for all six coins, not six models. The training pool mixes every coin's bars, the split is chronological — **the first 70% of days train, the last 30% validate** and are never seen during training — and the engine is gradient boosting. The signal fires when the model's score passes a threshold picked on train alone: τ = 0.87 for buy zones, 0.85 for sell zones. It transfers. On unseen days the signal still covers **74.5% of buy zones and 79.1% of sell zones**, against 85.7% / 89.8% on train. A drop, but not a collapse: what the model learned about one coin's turns is not coin-specific folklore. And now the number that decides everything. Of all the signal runs it produces on unseen days, **86.2% are false** — they fire where no zone was. Precision of a run is 0.209 for buys and 0.214 for sells. Read the two facts together: the signal finds most of the real turns *and* four out of five of its calls are wrong. It is a wide net, not a scalpel. There is a second, less comfortable finding in the feature importances. The top inputs are `pos_60` (0.331) and `pos_240` (0.240) — where the current price sits inside its own range over the last hour and last four hours — with `range_240` and `ret_5` behind them. Price geometry accounts for about 84% of the model's attention. The order-book features are in the input and they are not what the model leans on. A model that mostly says "the price is near the edge of its recent range" is a useful zone finder and a weak claim about the book. ## ③ Trading it: −122% against −93% for buy & hold A zone finder is not a trading system, and this is where the line stops being flattering. The rule we tested is the plainest one that follows from the signal: enter on the onset of a signal run confirmed by 2 bars, exit on the first opposite run or at the end of the session, 42-hour sessions, at most 12 trades a day — the project's standard. On unseen days, over six coins: **-122.3% net against -93.0% for buy & hold**. Positive on 0 of 6 coins, better than buy & hold on 1 of 6. Capture of the perfect trader's result: **-5.0%** — not a fraction of the ceiling, the wrong side of zero. BTC shows where the money goes. 66 trades, 1.51 a day, median holding 230 minutes, win rate 53% — more winners than losers. And still: | component | BTC, % over the period | |---|---| | winning trades | +23.3 | | losing trades | -46.1 | | fees paid | −17.2 | | **net** | **-22.8** | Gross per trade is -0.085% — **before any fee at all** — and net is -0.345%. That ordering matters. The fee is not what turns a winning rule into a losing one here; the rule has no edge to begin with, and the fee then triples the loss. Winning more often than losing is not the same as winning: the losers are simply bigger. (The fee in this test is 0.13% per action, the tariff at the time; the project's current standard is 0.15%, which makes this worse, not better.) Three things carry forward from this line, and all three shaped the bots we run now. A signal that *finds* turns is not a signal that *pays* for them — coverage and profit are different measurements. Anything that fires often must be gated, which is the subject of its own article. And the perfect-trader ceiling is the most useful number we built here: it turns "our strategy is down 5%" into "we captured −5% of what was there", which is a sentence you can act on. ================================================================================ # A Detector for Corrections Inside a Move — and Why It Took a New Way of Measuring URL: https://marketflowresear.ch/articles/a-detector-for-corrections-inside-a-move/ Published: 2026-08-31 · Series: Order-book research · Corrections, not exits > We stopped measuring how loud the order book is and started measuring how much wall stands per unit of aggression — eight features collapsed into four ratios. On that new scale a class appears that we could not see before: corrections inside a move, 5,396 of them, events that already look like a reversal without being one. Three detectors find them at 0.94 precision on a held-out half, and an external 0.8% zigzag confirms the class survives after loudness is matched away (×1.69). For a bot, that is the difference between holding a trend and being shaken out of it. ## ① Eight features become four ratios Every measurement system we built before this one asked the same question — *how loud is the market right now* — and every one of them ran into the same ceiling. A single number, the average level of six flow features, matched a convolutional network reading all 1,680 raw numbers of a window. Loudness was not one signal among many. It was the whole model. So this line changed what a window *is*. A 210-second event used to be a matrix of 210×8 raw numbers. Now it collapses in two steps: **Step one — eight averages.** For each of the eight order-book features, sum the 210 seconds and divide by 210. One number per feature per event. **Step two — four ratios.** Each side of the book is divided by the aggression that hits it. The seller's wall and the seller's net gain are divided by buy volume; the buyer's wall and the buyer's net gain are divided by sell volume: | number | what it measures | |---|---| | `const_resist / vol_buy` | how much seller wall stands per unit of buying | | `(resist_plus − resist_minus) / vol_buy` | how much seller wall is *gained* per unit of buying | | `const_support / vol_sell` | how much buyer wall stands per unit of selling | | `(support_plus − support_minus) / vol_sell` | how much buyer wall is *gained* per unit of selling | Eight numbers to four, and the four are no longer measures of volume. They are measures of **resistance per unit of pressure** — a ratio, so a quiet minute and a violent minute are directly comparable. That is the whole trick, and it is the reason everything below works. One rule about how these numbers are averaged, because it changes them by a factor of two. The ratio is computed **inside each event first**, and only then averaged over the class — every event weighs the same. Averaging the raw sums first and dividing afterwards weighs each event by its share of volume, and quiet windows, where the ratios are largest, almost vanish. On up legs the two conventions give 35.62 and 15.89 for the same set. We use the per-event one everywhere: the number in a table is exactly the centre of the cloud on the chart. The dataset is the cleaned BTC set: **31,212 windows** of 56,263, 175 days, 14 Feb – 8 Aug 2026. Inside it: 823 reversal windows of a 2.3% zigzag, 13,597 windows inside up legs, 15,814 inside down legs. A / (B + 1e-8) is the transform above; the tab shows every intermediate table. ## ② The correction: a reversal that isn't one A leg is a move of at least 2.3% in one direction. Inside it the price does not travel in a straight line — it stalls, pulls back, and continues. Those pauses are where a trading bot loses money: a stop gets hit, a position is closed, and the move resumes without you. So we asked the four numbers a narrow question: **which events inside a leg already look like a reversal, without being one?** The similarity is scored by a logistic regression trained on «reversal versus everything else», measured strictly out of fold — five contiguous time blocks with a 30-minute embargo, because a 210-second window is very close to its neighbour and without the embargo the model reads the answer off it. Out-of-fold **AUC 0.7474**. The threshold is the *median score of the true reversals*: a correction is an event that, in book terms, looks no worse than half of the real turns. That yields **2,563 corrections inside up legs** (18.9%) and **2,833 inside down legs** (17.9%). They are not a weaker version of a reversal. They **overshoot** it, in the same direction: | number (median) | reversal | correction | rest of the up leg | |---|---|---|---| | seller wall / buy volume | 11.40 | 6.64 | 29.45 | | buyer wall / sell volume | 10.54 | 6.89 | 28.08 | | wall difference (buyers − sellers) | -0.31 | 0.36 | -1.23 | The rest of the leg carries a thick wall per unit of aggression — 29.4 against 6.6 in a correction. The reversal sits *between* them. Read plainly: during a correction the walls thin out relative to the pressure hitting them, exactly as they do at a real turn, only more so. The three-dimensional map of a leg shows the same thing without any labels in the input: corrections occupy a continuous band of the cloud rather than a separate island. That is the honest shape of this class — a region, not a lump. ## ③ Matched for loudness, checked from outside Every claim in this project has to survive the same two questions: *is it just loudness*, and *does anything outside the model agree*. Corrections are louder than reversals — median volume 0.514 against 0.395 — so the first question is not optional. **Loudness matched.** Split the up-leg events into ten deciles of loudness (the sum of six flow features) and compare a correction only against the rest of *its own* decile. The external check is a small 0.8% zigzag, 672 pivots, which the model never saw: does the event stand within ±14 minutes of a small local turn? - corrections next to a small pivot: **31.2%** - expected if they behaved like their own decile: **18.5%** - lift after matching: **×1.69** - loudness on its own predicts nearness with AUC 0.597 The lift holds at 1.5–1.9 in nine deciles out of ten. For scale, true 2.3% reversals stand next to a small pivot 90.5% of the time — the check works. **Not a tail, a band.** Replace each number by its rank inside the leg — a monotone transform, order untouched — and the separation disappears: mean rank 0.519 / 0.523 for corrections against 0.495 / 0.495 for the rest. The reason is in the tails: only 9.6% of corrections have a wall difference beyond ±10, against 66.2% of the rest of the leg. The leg lives in both tails; the correction lives in the middle. No «greater than» threshold can catch that, which is precisely why a model is needed and why the earlier, cruder measurements missed it. **What we still cannot do.** Telling a real 2.3% reversal from a correction is a separate, much harder problem: AUC 0.670 on the four numbers against a shuffled-label null of 0.530, rising to 0.723 when loudness is added. Detecting *that something is happening* works. Deciding *whether the move ends here* does not, yet. ## ④ Three detectors, and what they are for Three detectors: one for up legs, one for down legs, one shared. The split is 50/50 by time — 20 contiguous blocks, even blocks train (15,606 windows), odd blocks validate (15,606). Contiguous on purpose: a random split lets the neighbouring window leak the answer. Two grids. The first picks the model family *and the input class*; the second tunes the winner's parameters while tracking the epoch curve, and takes the best epoch before overfitting. | model | precision | recall | signals | hits | targets | base rate | |---|---|---|---|---|---|---| | up leg | 0.939 | 0.951 | 1,352 | 1,270 | 1,336 | 20.3% | | down leg | 0.920 | 0.939 | 1,349 | 1,241 | 1,322 | 17.2% | | shared | 0.935 | 0.934 | 2,653 | 2,482 | 2,658 | 18.6% | All three chose the same input: **the four ratios**. Collapsing them further into two differences drops the best F1 from 0.93 to 0.61 — the class survives the step from eight numbers to four and dies at the step from four to two. That is the sharpest measurement result of this line. This looks like a breakthrough in detecting corrections, and it points at something practical: **a bot that recognises a correction does not close a position into one.** False exits are the cheapest money a trend-following system loses, and this is the first measurement we have that marks those moments while they happen, at 0.94 precision and 0.95 recall on data the model never saw. Two honest limits, stated plainly. The label itself comes from a threshold on the same four numbers, so the high precision proves the detector reproduces the class cheaply and reliably — it does not prove the class exists on its own; the independent evidence for that is the ×1.69 lift of the previous section. And a correction signal does **not** mean the move will run further: after a signal a leg has 12.6 hours left on average against 16.2 for an ordinary leg event. It marks a mature move, not a fresh one. Both limits become the next articles: an independent label, and the same detector on the five remaining coins. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. The measurement system — eight features to four ratios per unit of aggression — is what made this step possible, and it is the piece we carry forward. ================================================================================ # The Order Book Tells You How Far, Never Which Way URL: https://marketflowresear.ch/articles/the-order-book-tells-you-how-far-never-which-way/ Published: 2026-08-17 · Series: Order-book research · How far, not which way > We asked eight order-book features the same two questions at 16 horizons from one second to a day, on six coins: how far will the price move, and which way. Size answers — ρ 0.30 at a second, still 0.11 at an hour. Direction never does: -0.002 at a minute, -0.003 at a day. Then we bet real rules on both answers over 30 out-of-sample days: the volatility bet makes +4.97 bps a trade, the direction bet loses 5.95. This is the measurement that decides what our bots are allowed to bet on. ## ① Two questions, sixteen horizons Two questions look alike and are not. *How far will the price move in the next H seconds* asks for a size. *Which way* asks for a sign. We put both to the same eight order-book features, on the same windows, at **16 horizons from one second to 24 hours**, on all six coins — and let the answer be a pair of curves rather than an opinion. The size question answers. Averaged over the six flow features and six coins, the rank correlation with the size of the coming move is **ρ = 0.299 at one second**, 0.154 at a minute, 0.107 at an hour and 0.041 at a day. It decays, but it never turns into noise — at every horizon we measured, more flow means a bigger move. The direction question does not answer. The same features, the same windows, the same coins: **-0.003 at one second, -0.002 at a minute, +0.003 at an hour, -0.003 at a day.** Those are not weak signals that need a better model. On the scale of the left-hand curve they are a flat line at zero. The two constant walls behave differently from the flows, and in a way worth naming: their correlation with the coming move size is **negative** (-0.033 at a minute) — a thick standing wall goes with calm, not with a storm. It is the only stable directional-ish statement in this entire battery, and it is about volatility, not about which way the price goes. One consequence shapes everything we build. A bot that bets on *how much* is playing a game where the measurement supports it. A bot that bets on *which way* is, at these horizons, flipping a coin with a fee attached. ## ② A spike is activity, not a side Why should a burst of order-book activity say nothing about direction? Look at what an event actually is. Take every moment a feature spikes above its own normal level and measure the next five minutes: | feature | volatility after the spike | share that went up | |---|---|---| | support_minus | ×1.66 | 0.495 | | vol_buy | ×1.46 | 0.486 | | vol_sell | ×1.56 | 0.482 | | const_resist (wall) | ×1.00 | 0.505 | | const_support (wall) | ×1.04 | 0.500 | Every flow feature multiplies the next five minutes' volatility by 1.46–1.66. Every one of them splits up and down within a few points of **0.500**. Even `vol_buy` — literally the volume of aggressive buying — is followed by an up move 48.6% of the time. Buying pressure does not mean the price goes up; it means *something is happening*, and the other side is usually there to meet it. The walls are the control that makes the reading credible. A spike in a standing wall gives ×1.00 and ×1.04 — no effect at all. If our measurement were picking up some generic "activity" artefact, the walls would show it too. They do not. The mirror image of the same fact is the quiet market. Split the tape into rising, falling and sideways stretches and measure the flow level in each: rising -0.04σ, falling -0.03σ, **sideways -0.42σ**. A sideways market is not a market with balanced buying and selling — it is a market where the flows have frozen. That is why "how far" is predictable at all: activity clusters. The BTC autocorrelation of `vol_buy` confirms the clustering directly — 0.506 at one minute, 0.608 at an hour, still 0.352 at a day. Loud stays loud for hours; up does not stay up. ## ③ Betting on size, and the graveyard of direction bets If size is predictable and direction is not, the honest test is a bet on size. We ran four rules on **30 out-of-sample days**, six coins, 24-hour holding, 6 bps of cost per round trip, with the volatility forecast (ρ = 0.253 pooled, 0.30 on BTC) as the only input: | rule | trades | net per trade | win rate | Sharpe | |---|---|---|---|---| | long volatility (bet a big move comes) | 3,687 | +4.97 bps | 41.6% | +0.143 | | straddle (both sides) | 6,272 | +1.78 bps | 49.1% | +0.059 | | short volatility (bet on calm) | 2,585 | -2.77 bps | 59.9% | -0.129 | | direction momentum | 10,184 | -5.95 bps | 38.1% | -0.153 | Read the win-rate column against the money column and the shape of this market becomes visible. Long volatility wins only 42% of the time and still makes +4.97 bps per trade — most bets are small losses paid for by rare large wins. Short volatility wins 60% of the time and loses money — many small wins wiped out by the occasional storm. That asymmetry is not a bug in the rule; it is what a fat-tailed market looks like from the inside. The directional rule is the one to keep in mind: 10,184 trades, **-5.95 bps each**, Sharpe -0.153. It is the same result the horizon curves predicted, now counted in money. And it is not an isolated failure — a separate intraday directional test over the same data finished at **-346% net across 1,344 trades with a 19.3% win rate**. Two limits before anyone builds on this. First, +4.97 bps per trade is a real edge and a thin one: it survives 6 bps of cost and would not survive much more, so execution is not a detail here, it *is* the strategy. Second, the forecast decays with horizon — strong at seconds, weak at a day — so this edge lives at short holdings and disappears if you stretch it. What we take forward: our bots are allowed to ask "is a move coming and how big", and they are never allowed to answer "which way" from these features alone. Direction has to come from somewhere else — the geometry of the price itself — and that is a separate line of work. ================================================================================ # We Taught a Network to See a Move. It Only Heard How Loud It Was. URL: https://marketflowresear.ch/articles/we-taught-a-network-to-see-a-move-and-it-only-heard-how-loud-it-was/ Published: 2026-08-15 · Series: Order-book research · Moves, not noise > We trained three networks on the same 56,263 order-book windows and learned two things we did not want to learn. A single number — how loud the window is — matches a convolutional network on all 1,680 of them (0.7575 against 0.7571). And once you match windows by that number, the inflow features that carried the whole model separate nothing at all. What does survive is small, directional, and points at a different kind of bot than the one we set out to build. ## ① Three targets and an honest split We had a cleaned dataset and no idea whether the cleaning meant anything. The chain that produced it — density clustering, then k-means, then k-means again — threw away 25,051 of 56,263 windows and kept 823 of 863 reversal windows. So the discarded part earned a name: **«no reversal possible»**. Over 175 days it contains 40 reversal windows in total. Three networks, one recipe. Each sees exactly 1,680 raw numbers of a 210-second window — no price, no time of day, no normalisation against history, no answers from other detectors. | target | windows | positives | base rate | |---|---|---|---| | «no reversal possible» | 56,263 | 25,051 | 44.52% | | cleaned dataset (the mirror) | 56,263 | 31,212 | 55.48% | | reversal, inside the cleaned data | 31,212 | 823 | 2.64% | The split matters more than the architecture. The timeline is cut into 50 contiguous chunks of equal window count, and the chunks are dealt into five parts so that each part holds a proportional number of **reversals** — not just a proportional number of windows. The result: 11,253-11,252 windows and 172-174 reversal windows per part. Each part is the test set once; a 30-minute embargo keeps the neighbouring window out of training, because a 210-second window is very close to its neighbour and without the embargo the model simply reads the answer off it. Architecture is chosen by a grid of 18 configurations on a **different** split — screening parameters on the same folds you report is peeking. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. Every number below is the honest, out-of-fold kind: each window scored by a model that never saw it. ## ② The ceiling: one number, and what is under it The two mirror targets are learned almost perfectly. The reversal is not. | target | dilated conv on 1,680 numbers | logistic regression on 8 levels | boosting on 40 descriptors | null control | |---|---|---|---|---| | «no reversal possible» | 0.9854 | 0.9840 | **0.9926** | 0.4885 | | cleaned dataset | 0.9877 | 0.9840 | **0.9926** | 0.4887 | | reversal | 0.7571 | **0.7564** | 0.7406 | 0.4851 | Two things to say plainly. First, the network **lost in all three targets** — to boosting on 40 descriptors in the mirror pair, and to a logistic regression on eight numbers in the reversal task. Fourth line of this project to end that way. Second, and more important: the mirror labels are a deterministic function of the same 1,680 numbers, so 0.99 proves nothing by itself. What it does prove is that the boundary **holds on time the model never saw** — the null control, the same label shifted along the time axis, sits at 0.488. Then we measured the ceiling. One number — the mean level of the six flow features in the window, what we call loudness — separates a reversal from the rest of the cleaned dataset at AUC **0.7575**. The network on all 1,680 numbers: 0.7571. So we matched them. For each of the 823 reversal windows we picked a non-reversal window with the nearest loudness (3.9189 against 3.9188; the AUC of loudness itself is now exactly 0.500). Everything that survives that is no longer level — it is composition. | measured on loudness-matched windows | AUC | |---|---| | the four inflow/outflow features | 0.510 — 0.501 (nothing) | | both const walls | 0.433 (thinner on a reversal) | | both volumes | 0.539 | | volumes minus walls | **0.565** | The inflow — the thing carrying the entire performance of the current model — separates **nothing** once loudness is equalised. What is left of a reversal is thinner constant walls and slightly more volume, worth about 0.56 AUC. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. A model whose skill equals a single average is not a model we can improve by making it deeper. That is why the next one will not be built on level at all. ## ③ Direction: invisible in the move, visible at the turn If the book cannot tell a reversal from an ordinary loud moment, can it at least tell **which way** the market is going? We split the question in two, because the answers turn out to be opposite. **Inside the body of a move** — nothing. 13,597 windows in an up-leg against 15,814 in a down-leg, loudness practically identical (3.350 against 3.327), and after correcting for it no feature moves further from 0.5 than 0.032. The order book does not know which half of the move it is in. That reproduces what a different line of this project found on 40 descriptors, by a different road. **At the turn itself** — quite a lot. 407 tops against 416 bottoms: | measured inside deciles of loudness | AUC towards the top | |---|---| | loudness — control | 0.507 | | vol_sell | **0.617** | | const_support | 0.587 | | both const walls | 0.569 | | support_plus | 0.399 (i.e. towards the **bottom**) | The correction is not cosmetic. In the raw levels `vol_sell` is *higher at bottoms* (0.353 against 0.224) — because bottoms are simply louder events (4.029 against 3.807). At equal loudness the sign flips and selling volume marks the **top**. A textbook Simpson's paradox sitting in the middle of a trading dataset. And one quantity tracks the direction of the move without being a shadow of loudness at all — the net growth of a wall per unit of aggression hitting it, `(inflow − outflow) / volume`: | period | sell wall per unit of buying | buy wall per unit of selling | |---|---|---| | bottom | **18.42** | 13.87 | | leg down | 19.16 | 15.58 | | leg up | 16.80 | 17.09 | | top | 14.47 | **16.95** | | non-reversal, loudness-matched | 17.07 | 17.47 | In a fall the sellers' wall rebuilds faster per unit of buying; in a rise, mirror image; in a matched ordinary moment, balance. In the quietest and the loudest subsets the gap is the same size, so this is not level in disguise. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. This is the first directional quantity in the series that survives the loudness correction, and it points at a specific kind of bot: not one that predicts direction, but one that decides whether to **keep holding**. ## ④ A week the models had never seen Everything above is measured on data the models were trained on, out of fold. The last check is different: 2,506 windows recorded **after** the dataset was frozen — 6.54 days the networks could not have seen, scored with frozen weights and frozen thresholds, nothing retrained, nothing recalibrated. | model | fires on the fresh week | fired on the training period | |---|---|---| | «no reversal possible» | **70.75%** | 44.50% | | cleaned dataset | 30.97% | 55.44% | | reversal | 0.16% | 1.57% | The week reads, to the order book, as markedly less reversal-capable than the average of the dataset. We cannot check that against a label: the cleaning chain rests on density clustering, and density clustering cannot assign new points to old clusters. So on fresh data these two targets have a model answer and no ground truth — we report the frequency and nothing else. What we *can* check is the two mirror models against each other. They were trained separately, on opposite labels, with different architectures chosen by different grids. On the fresh week they disagree on 187 windows out of 2,506 — 7.5%. That number is their own noise floor, and it is small. A footnote worth keeping: in 6.5 days the 2.3% zigzag produced exactly **one** raw pivot and zero completed legs. Not a flat market — the price moved -3.10% — simply too short a stretch for alternating 2.3% legs. Anyone validating a reversal model on a week of data is validating it on one event. **What is next.** The direction quantity from the previous section goes into a written specification — **MOVE_HOLD.md**, downloadable below — for a *holding* indicator rather than an entry signal: the trade is already open, and the question is whether the book still supports the move. The document states the metric (percentage of the leg captured, measured on 120 legs rather than on windows), the seven traps, a table of control numbers with tolerances, and the list of directions already closed so nobody re-opens them. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. And it names the number that would kill the idea: if the quantity falls inside the null control at the level of moves, the holding indicator closes exactly as direction prediction did. ================================================================================ # A Recipe, Not a Result: How We Clean an Order-Book Dataset URL: https://marketflowresear.ch/articles/a-recipe-not-a-result-how-we-clean-an-order-book-dataset/ Published: 2026-08-14 · Series: Order-book research · Dataset cleaning recipe > This is the least glamorous and most useful study of the series: not a finding, but a procedure. How to take a raw dataset of order-book windows and produce a clean one — 56,263 windows in, 31,212 out, 95% of the reversals still there — with every step checked, every trap written down, and the whole thing runnable on another coin by one command. ## ① The chain: four narrowings The chain has four narrowings, each justified by the step before it. | step | windows left | reversal windows left | what was removed and why | |---|---|---|---| | raw dataset | 56,263 | 863 | — | | cleaned | 37,519 | 847 | two independent definitions of "quiet" | | 6 features | 37,519 | 847 | the const walls dropped from the **input** | | 4 features | 34,949 | 839 | volumes dropped too; classes with no reversals removed | | smaller still | 32,736 | 832 | two small classes, a human decision | | one more | 31,212 | 823 | a class that owned no turning point at all | The important discipline: every removal is decided by a label found **on the same data**, so the reversal rate in what remains rises mechanically — from 2.26% to 2.64%. That is arithmetic, not discovery, and it means the lift numbers of different steps must never be compared with each other. What *can* be compared is whether the axis stays put. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. Data preparation is the part nobody publishes and everybody re-does badly. Writing it down once is how the rest of this project stops repeating itself. ## ② Eight features, six, four Two of the steps ask a question worth asking on its own: which of the eight features are actually doing the work? | input | k-means agreement with the previous step | HDBSCAN classes | the reversal-rich class | |---|---|---|---| | 8 features | — | 5 | ×2.63 | | 6 (both const walls dropped) | ARI 0.968, 99.2% of windows | 3 | ×2.38 | | 4 (volumes dropped too) | ARI 0.691, 91.7% | 2 | ×2.10 | Dropping the walls changes essentially nothing — k-means agrees with itself on 99.2% of windows — and what disappears from HDBSCAN are exactly the small wall-shaped classes that had no reversals in them anyway. Dropping the volumes moves the boundary noticeably more, but the axis is still the same axis: the class widens, catches more reversals and therefore shows a lower lift. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. Four features instead of eight is half the input a live model has to compute every second — worth knowing that it costs nothing. ## ③ Where to stop, and how you know Where does this stop? Not at a number of steps, but at a diagnostic. | step | stability of the split (rebuilt on another seed) | largest class holds | |---|---|---| | the cleaned set | 0.796 | 0.787 | | 6 features | 0.667 | 0.757 | | 4 features | 0.716 | 0.845 | | minus two small classes | 0.685 | 0.890 | | minus one class more | 0.056 | 0.982 | The method's own ceiling is 0.65 for the largest share: above it, the split is "almost everything against a crumb", which reproduces itself out of nothing. The fourth narrowing crosses it decisively — 0.982 with stability collapsing to 0.056 — while k-means still agrees with the previous step at ARI 0.938. So it is the density-based split that dies, not the axis. The last removal is instructive on its own. The class we dropped held 10 reversal windows spread across 8 different turning points, dominated none of them and owned none entirely — an average share of 0.017 per turn. Its reversal windows were *quieter than its own ordinary windows*. Nothing was lost. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. Knowing when to stop cleaning is worth as much as knowing how to clean: an over-trimmed dataset trains a model that only works on the trimming. ## ④ The recipe itself The whole procedure is published as an executable recipe — **CLEANUP_DATASET.md**, downloadable below. It contains the input format and the minimum data volume, the exact order of commands, each step with its control number, ten traps we walked into, a table of control values with tolerances, and the full source code pulled automatically from the working files, so it cannot drift from what actually runs. The mechanical part is one command; the chain then stops by itself where a human decision begins and prints the table of candidates. A few of the traps, since they generalise well beyond this project: | trap | what happens if you ignore it | |---|---| | judging a clustering by the number of classes | our hard null produced 11 classes at the same noise share as real data | | measuring stability in a fixed space | the same setting gave 12 classes on a fixed map and 5 on a full rebuild | | throwing away the noise | it holds about a third of all reversal windows | | counting windows instead of events | one turning point produces up to nine windows | **What is next.** With a clean dataset and a written recipe, the series moves back to the thing all of it is for: turning the "inflow" axis into a signal that survives fees. That means intersecting it with a second, independent signal, testing it on the other five coins, and measuring the whole chain — detector, then side, then entry — end to end. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. We are not there yet, and we will say so plainly when a number does not clear the 0.30% round-trip cost. ================================================================================ # Throwing Away a Third of the Data and Keeping 98% of the Reversals URL: https://marketflowresear.ch/articles/throwing-away-a-third-of-the-data-and-keeping-the-reversals/ Published: 2026-08-14 · Series: Order-book research · The cleaned dataset > If a third of your data provably contains almost nothing you are looking for, it should not be in the training set. We removed 18,744 of 56,263 windows — everything two independent definitions of 'quiet' agree on — and kept 98.1% of all the reversal windows. ## ① What was removed, and what it cost Two sets are subtracted, and they overlap, so what is removed is their **union**, not their sum: | what we remove | windows | reversal windows in it | |---|---|---| | noise 1.1 — the quiet half of the quiet half of the noise | 18,320 | 16 | | every window where the quiet-PCA model fires, warm-up included | 4,598 | — | | **what remains** | **37,519** | **847 of 863** | The second set is worth a note. The quiet-PCA label needs an external 28-day norm, so it does not exist for the first 28 days of the dataset — but the *model* does not need the norm, it only needs the window's own 1,680 numbers. So we ran it across the entire dataset, warm-up included: 235 firings there against 2.4% of windows, versus 9.4% on the labelled part. Honestly: on the warm-up there is nothing to check it against. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. Training is the slow step of everything we do. A third fewer windows at 98% of the signal is a third more experiments per day. ## ② The cleaned set splits the same way Cluster the cleaned set exactly as before, and nothing structural changes. | split | classes | the reversal-rich one | reversals | versus base (2.26%) | |---|---|---|---|---| | k-means | K=2 | 10,164 windows | 569 | ×2.48 | | HDBSCAN | 5 + 77% noise | 6,725 windows | 399 | ×2.63 | Two of the HDBSCAN classes contain exactly zero reversals, which is itself useful: those are shapes of the book that never sit on a turn. That the same axis appears again after removing a third of the data is the check that the removal was legitimate. If the cleaning had cut into the signal, the classes would have moved. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. Same structure, fewer windows, denser reversals — that is what "cleaned dataset" has to mean before anything is trained on it. ## ③ What a reversal window actually looks like What does a reversal window actually look like? Averaged cell by cell over all 847 of them against the 36,672 others: | feature | reversal windows | all others | ratio | |---|---|---|---| | const_resist | 2.29 | 2.47 | ×0.93 | | resist_plus | 7.37 | 3.78 | ×1.95 | | resist_minus | 2.79 | 1.48 | ×1.89 | | const_support | 2.12 | 2.42 | ×0.88 | | support_plus | 6.98 | 3.55 | ×1.96 | | support_minus | 2.72 | 1.44 | ×1.89 | | vol_buy | 0.28 | 0.13 | ×2.14 | | vol_sell | 0.28 | 0.13 | ×2.13 | All six flow features roughly double. Both const walls go slightly *down*. Splitting the 210 seconds into three blocks changes nothing — the picture is identical at the start, the middle and the end of the window, so it is the **level** that carries the information, not the shape inside the window. Split the reversals into tops and bottoms and the effects are much smaller but consistent: every flow feature is higher at a bottom, most strongly `vol_sell`, while the walls are identical. That matches the previous study — a bottom is a louder event than a top. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. "Level, not shape" is a design decision for the bot: it means a handful of averages can stand in for a neural network, and averages are cheap to compute in real time. ## ④ Cutting finer: purity for coverage Finally, cut the cleaned set finer with k-means and watch the trade-off. | K | the best class | windows | reversals in it | versus base | |---|---|---|---|---| | 3 | class 2 | 8,954 | 540 | ×2.67 | | 5 | class 4 | 3,287 | 320 | ×4.31 | | 7 | class 5 | 1,798 | 212 | ×5.22 | | 10 | class 1 | 1,145 | 139 | ×5.38 | Purity roughly doubles from K=3 to K=10 — and the number of reversals actually caught falls by three quarters. That is an exchange rate, not a discovery: no new class appears, the same "inflow" region is simply being sliced thinner. The data supports K=2; everything beyond it is description. **What is next.** One more study closes this series: the full cleaning procedure written down as an executable recipe — every command, every trap, every control number with a tolerance — so it can be re-run on the other five coins and on future data without re-deriving it. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. That recipe is what turns a set of experiments into infrastructure a bot can be built on. ================================================================================ # Twenty-Five Weeks, Twenty-Five Rebuilds: Which Clustering Survives URL: https://marketflowresear.ch/articles/twenty-five-weeks-twenty-five-rebuilds-which-clustering-survives/ Published: 2026-08-14 · Series: Order-book research · Week by week > A clustering that only exists once is a story, not a result. So we rebuilt it 25 times — every week of the dataset from scratch, its own PCA, its own UMAP, its own clusters — and compared each week with the answer found on the whole dataset. One of the two methods reproduces. The other does not, and it is the fashionable one. ## ① Rebuilt, not scored The protocol is deliberately harsh. A week is not *scored* by the global model — it is *rebuilt* completely: its own feature scale, its own PCA, its own UMAP, its own clusters, with min_cluster_size scaled to the week's size. Only then are the two label sets compared, by adjusted Rand index, which is invariant to how the classes happen to be numbered. | | value | |---|---| | weeks in the dataset | 26 (25 large enough to count) | | windows per week | from 707 to 2,831 | | what is compared | each week's labels against the labels of the full-dataset run | Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. A bot retrains on a rolling window of recent data, so "does this structure exist in any given week" is not an academic question — it is the difference between a model that can be refreshed and one that has to be rediscovered every time. ## ② k-means: the same answer every week k-means reproduces itself, and it does so twice over. | | value | |---|---| | weeks that chose the same K on their own | 0 of 25 | | median agreement with the global split | 0.699 | | worst week | 0.138 | | best week | 0.988 | Every single week, independently, decided that its own data supports the same number of classes, and in a typical week the labels agree with the global ones on the great majority of windows. The bad weeks are not random either — they are the small ones, where the number of windows drops. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. This is the result that makes the whole line usable: the "is there inflow" axis is a property of the market, not of the particular five months we happened to collect. ## ③ HDBSCAN: two classes or seven, depending on the week HDBSCAN does not reproduce. | | value | |---|---| | median agreement with the global split | 0.216 | | range across weeks | -0.029 … 0.318 | | classes found per week | from 2 to 7 | | noise share per week | from 0% to 66% | Same method, same settings, same market — and depending on the week it returns two classes with almost no noise, or seven classes with two thirds of the data unplaced. It is not wrong; it is sensitive to sample size in a way that k-means is not, and a week is a much smaller sample than five months. This matches what the earlier studies in this project found on a monthly split, and it is the reason we report *both* methods everywhere instead of picking the one with the nicer picture. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. An unstable partition cannot be a production feature. If a class exists in June and not in July, a bot that keys on it is trading a calendar. ## ④ What survives, and what that means in practice **What we keep from this.** The axis is stable; the density-based subdivision of it is not. In practice that means: use k-means (or, better, the explicit threshold rules it implies) for anything that has to run continuously, and use HDBSCAN only to explore — with a full rebuild and a hard null every single time. There is also a warning in these numbers for anyone reading clustering results in general. The hard null in this project regularly produces *more* classes than the real data, at the same noise share. If a study reports "we found seven clusters" without saying what shuffled data produces, that sentence carries no information at all. **What is next.** With the stable part identified, the following studies use it to clean the dataset: remove what provably carries no reversals, check what is left, and write the whole procedure down as a repeatable recipe so it can be run on the other five coins. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. A smaller, denser dataset trains faster and lets us test more ideas per day, which is the entire bottleneck of this project right now. ================================================================================ # Tops Hide, Bottoms Don't: an Asymmetry We Did Not Expect URL: https://marketflowresear.ch/articles/tops-hide-bottoms-do-not-the-asymmetry-we-did-not-expect/ Published: 2026-08-14 · Series: Order-book research · The falling half > This is the mirror of the previous study: the fall from a top to a bottom, 27,180 windows, the same pipeline to the letter. The structure repeats — and one number does not. Tops hide from the order book four times more often than bottoms do. ## ① The mirror image of the previous study The zigzag with a 2.3% threshold cuts the price into legs: every leg runs from one turning point to the next. Take only the falling half — the turn itself (±15 minutes around the pivot) plus the whole leg that follows it — and cluster **only** those windows, with the feature scale recomputed on this subset so that nothing from outside leaks in. | the set | value | |---|---| | windows of 210 s | 27,180 | | reversal windows in them | 431 (1.59%) | | legs of the zigzag in the dataset | 120, average 33.9 h | One objection has to be said out loud before any number: **the zigzag knows the future.** A leg is only a leg once the next turn has happened. So a class found inside one half of a move is not, by itself, something a live bot can use — it first has to know which half it is in. We measure that separately, and the answer is that the book barely knows. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. Which is why this study is a measurement, not a strategy: it tells us how much of the structure we see is really about the direction of the move. ## ② The structure repeats exactly Same result as on the whole dataset, and that is the point of running it: the split does not change when we restrict it to one half of the move. | split | classes | the reversal-rich one | reversals in it | versus base | |---|---|---|---|---| | k-means | K=2 | 6,928 windows (25%) | 312 | ×2.84 | | HDBSCAN | 5 + noise | 6,335 windows | 273 | ×2.72 | The quiet classes hold almost no reversals at all, the noise holds 156 of them at ×0.50. Stability is 0.764 against 0.207 for the hard null. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. A filter that works the same way in both halves of a move is a filter that does not need to know the direction — which is the only kind we can put in a bot. ## ③ Counted as turning points Counting reversal windows is misleading on its own. Windows step every 210 seconds, so up to nine of them fit into the ±15-minute band around a single pivot: one cluster of windows easily looks like nine separate events. So everything gets recounted per **turning point**, with the metric being the *share* of a turn's windows that a class holds — 1.0 if the turn lies in it entirely, 0.03 if it holds one window out of thirty. | | windows | turning points touched | where it holds the largest share | turns lying in it entirely | |---|---|---|---|---| | noise | 156 | 43 | 22 | 3 | | class 0 | 0 | 0 | 0 | 0 | | class 1 | 0 | 0 | 0 | 0 | | class 2 | 0 | 0 | 0 | 0 | | class 3 | 273 | 51 | 33 | 12 | | class 4 | 2 | 2 | 0 | 0 | 431 reversal windows belong to 55 distinct turns — 7.84 windows per turn. The noise holds an average share of 0.365 of a turn. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. For a bot this is the difference between "we catch 200 signals" and "we catch 30 events, several times each" — and only the second number is real. ## ④ The asymmetry: a top is a quieter event Everything about the two halves matches: the same K, nearly the same class sizes, nearly the same enrichment of reversals. The asymmetry is in what the clustering *fails* to place. | | bottoms (rising half) | tops (falling half) | |---|---|---| | average share of a turn's windows landing in noise | 0.092 | 0.365 | | turns with any window in noise | 12 of 54 | 43 of 55 | | turns with half or more in noise | 5 | 22 | | turns lying **entirely** in noise | 0 | 3 | At a bottom the book always says something: not one bottom disappears completely. At a top three do, and half the tops have most of their windows unplaced. A top, it seems, is more often a quiet event — buyers simply stop arriving — while a bottom is loud, because someone has to step in front of a falling price. **What is next.** Before trusting any of this, it has to survive being rebuilt on different data — so the following study redoes the whole clustering week by week, 25 times from scratch, and compares each week with the global answer. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. And a bot that shorts tops on an order-book signal needs to know that its signal is weaker there, by design. ================================================================================ # The Rising Half of a Move: What the Order Book Looks Like Between a Bottom and a Top URL: https://marketflowresear.ch/articles/the-rising-half-of-a-move-what-the-order-book-looks-like/ Published: 2026-08-14 · Series: Order-book research · The rising half > Half of every price move is a climb from a bottom to a top. We took only that half — 26,921 windows of the order book — and clustered it blind. The structure that comes out is the same one the whole dataset gives, which is good news: it means the classes are not an artefact of mixing rises and falls together. ## ① Cutting the data by the geometry of the move The zigzag with a 2.3% threshold cuts the price into legs: every leg runs from one turning point to the next. Take only the rising half — the turn itself (±15 minutes around the pivot) plus the whole leg that follows it — and cluster **only** those windows, with the feature scale recomputed on this subset so that nothing from outside leaks in. | the set | value | |---|---| | windows of 210 s | 26,921 | | reversal windows in them | 432 (1.60%) | | legs of the zigzag in the dataset | 120, average 33.9 h | One objection has to be said out loud before any number: **the zigzag knows the future.** A leg is only a leg once the next turn has happened. So a class found inside one half of a move is not, by itself, something a live bot can use — it first has to know which half it is in. We measure that separately, and the answer is that the book barely knows. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. Which is why this study is a measurement, not a strategy: it tells us how much of the structure we see is really about the direction of the move. ## ② The same axis, restricted to one half Same result as on the whole dataset, and that is the point of running it: the split does not change when we restrict it to one half of the move. | split | classes | the reversal-rich one | reversals in it | versus base | |---|---|---|---|---| | k-means | K=2 | 6,131 windows (23%) | 334 | ×3.40 | | HDBSCAN | 4 + noise | 10,334 windows | 389 | ×2.35 | The quiet classes hold almost no reversals at all, the noise holds 42 of them at ×0.17. Stability is 0.795 against 0.146 for the hard null. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. A filter that works the same way in both halves of a move is a filter that does not need to know the direction — which is the only kind we can put in a bot. ## ③ Counted as turning points, not as windows Counting reversal windows is misleading on its own. Windows step every 210 seconds, so up to nine of them fit into the ±15-minute band around a single pivot: one cluster of windows easily looks like nine separate events. So everything gets recounted per **turning point**, with the metric being the *share* of a turn's windows that a class holds — 1.0 if the turn lies in it entirely, 0.03 if it holds one window out of thirty. | | windows | turning points touched | where it holds the largest share | turns lying in it entirely | |---|---|---|---|---| | noise | 42 | 12 | 5 | 0 | | class 0 | 389 | 54 | 49 | 42 | | class 1 | 0 | 0 | 0 | 0 | | class 2 | 0 | 0 | 0 | 0 | | class 3 | 1 | 1 | 0 | 0 | 432 reversal windows belong to 54 distinct turns — 8.0 windows per turn. The noise holds an average share of 0.092 of a turn. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. For a bot this is the difference between "we catch 200 signals" and "we catch 30 events, several times each" — and only the second number is real. ## ④ The reversals that fall into the noise Some reversal windows fall into the noise — 42 of them from 12 different turns. Are those special reversals the clustering failed to see? No. They are the **quiet edge** of the same event: | where the reversal window sits | resist_plus level | |---|---| | in the reversal-rich class | 8.84 | | in the noise | 2.17 | | ordinary windows of the noise | 1.60 | A turn lasts long enough to produce both loud and quiet windows. The loud middle lands in the class, the quiet edges fall out into the noise — and not a single turn lies entirely in the noise, which is the check that settles it. **What is next.** The mirror study: the falling half of the move, built exactly the same way. Comparing the two is where the one genuinely unexpected result of this pair shows up. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. And a bot that trades tops and bottoms has to know whether the book treats them the same way. It does not. ================================================================================ # One Axis, Again: Clustering 56,000 Order-Book Windows Without a Teacher URL: https://marketflowresear.ch/articles/one-axis-again-clustering-order-book-windows-without-a-teacher/ Published: 2026-08-14 · Series: Order-book research · Classes without a teacher > Take 56,263 windows of the order book, 210 seconds each, eight features per second. Tell the algorithm nothing — not the price, not the time, not our own signals. Ask only one thing: does this pile of windows fall apart into groups by itself? It does, along exactly one axis, and that axis is not the one anybody hopes for. ## ① The method, and the three guards that make it mean something The recipe is deliberately boring, because the guards matter more than the method: PCA to 32 dimensions, then k-means with K from 2 to 10, and in parallel UMAP to 10 dimensions and HDBSCAN. The 2-D map you see in the charts is *only* a map — clusters are never searched for on it. Three guards run beside every split: | guard | what it does | why it is not optional | |---|---|---| | hard null | shuffles each column between windows, destroying everything except the marginal distributions | it produced 11 "classes" with 78% noise — nearly the same as the real data | | stability | rebuilds the **entire** pipeline with a different seed and compares labels | a repeat clustering in a fixed space overstates it, sometimes twofold | | max_share | share of the largest class among clustered points | a "nearly everything versus a crumb" split reproduces itself and looks stable out of nothing | The real split scores 0.724 stability against 0.171 for the null. That gap — not the number of classes, not the share of noise — is the only thing that says the structure exists. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. A bot trained on classes that a shuffled dataset can also produce is a bot trained on nothing, so this is where the money is saved. ## ② One axis: is there inflow, or is there not K=2, chosen by how far the silhouette beats the null rather than by the silhouette itself. | class | windows | resist_plus level | reversal windows | versus base | |---|---|---|---|---| | the one with inflow | 13,586 (24%) | 6.36 | 659 | ×3.16 | | the one without | 42,677 (76%) | 1.84 | 204 | ×0.31 | The whole difference is the flow features — inflow and drain on both walls — while the const walls themselves stand at the same level in both classes and take no part in the division. HDBSCAN, a completely different algorithm, finds the same thing: its reversal-rich class carries them at ×2.87, and its wall-shaped class has essentially none. And the reversals: ARI against the reversal label is 0.044 and 0.029, against the phase of the zigzag 0.009. In plain words, **the split is not a reversal detector**. Reversals are merely three times denser on one side of the axis than on the other. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. This is the honest ceiling of unsupervised work here: it hands a bot a filter that triples the density of what it is looking for, not a signal it can trade. ## ③ 'Noise' is not a mystery, it is a level HDBSCAN leaves 72% of the windows unassigned, and "noise" sounds like "the algorithm gave up". So we asked whether the noise can be told apart from everything else — and it can, almost trivially. | how we separate noise | AUC, out-of-fold on blocked splits | |---|---| | boosting on a 32-dimensional PCA space | 0.974 | | one number — the mean level of the six flow features | 0.874 | | the null (the same label shifted in time) | 0.455 | There is even an explicit rule with no model at all: if that one number falls in the band **-0.379 … 0.256**, the window is noise. It covers 66% of all windows, is 92.3% pure, and catches 85.0% of all the noise there is. So noise is not a mystery — it is the quiet end of a single scale. Worth knowing before building anything on top of it: the ceiling of this task is 91.7%, because that is how often the label reproduces *itself* when the clustering is rebuilt with another seed. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. Cheap, explainable rules like this band are what actually survive into production; a model that costs 30× more and scores the same is a liability. ## ④ Two independent definitions of a quiet market Cut the noise once more and its quiet half — we call it **1.1** — is 18,320 windows with 16 reversal windows in them: ×0.28 the base rate, which is to say practically dead. We already had a separate, independently trained detector of quiet market — "quiet PCA", built with an external 28-day norm. Do the two agree? | | windows | reversals | |---|---|---| | both | 3,937 | 1 | | only 1.1 | 12,674 | 8 | | only quiet-PCA | 493 | 0 | | neither | 29,286 | 614 | 89% of quiet-PCA lies inside 1.1, but takes only 24% of its volume: 1.1 is the wider "quiet", quiet-PCA its narrow core. What separates them is **wall thickness** (const_resist 4.06 in the quiet-PCA-only group against 2.69 elsewhere) — that is what the external norm adds, not the fact of silence itself. **What is next.** Two studies that cut the same dataset by the geometry of the move — the rising half and the falling half — and one that rebuilds everything week by week to see what survives. Then we use what we learned here to throw the dead part of the dataset away. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. Fewer windows, same reversals, cheaper training. ================================================================================ # One Network for Three Market States: What a Pooled Reversal Model Learns URL: https://marketflowresear.ch/articles/one-network-for-three-market-states/ Published: 2026-08-14 · Series: Order-book research · Pooled reversal model > We trained one network on the events of three different market states at once — 55,929 events, 3,758 of which sit on a real turning point — and asked it a single question: is this event a reversal or an ordinary event of its own class? The answer is interesting in a way we did not plan: the model works, the validation set lies about which model is best, and an unsupervised split of the same pool finds classes that have nothing to do with reversals at all. ## ① One pool, three states, one subtraction Three detectors mark events in our data: **storm** (loud order book), **calm** (quiet), **class 2** (the middle). Until now each had its own model. Here they share one, and the trick that makes that possible is subtraction: before an event goes into the network, we subtract from it the **average event of its own class over the past 30 days**. The network never sees "a loud event" or "a quiet event" — it sees *how much this event differs from what its class normally looks like*. The base is strictly causal: for an event at time *t* it is built from events strictly before *t*, and validation and test events are excluded from it entirely. Otherwise the base would be quietly looking at its own answer. | class | events in the pool | of them on a reversal | share | |---|---|---|---| | storm | 5,124 | 1,060 | 20.7% | | calm | 29,201 | 737 | 2.5% | | class 2 | 21,604 | 1,961 | 9.1% | Read the last column, not the middle one. A reversal is one event in five inside a storm and one in forty inside calm — the same phenomenon is common in one state and rare in another, which is exactly why a single model trained on the union has to be told which state each event came from. Subtracting the class base is how we tell it. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. This step is the plumbing for that: one model instead of three is one thing to maintain, retrain and monitor when it eventually runs live. ## ② The model works. The validation set lies. The split is blocked in time: the timeline is cut into 50 chunks, five go to validation and five to test, every other one, with a 30-minute embargo around each. Then 18 architectures are screened, the best three are trained to 48 epochs, and the answers are read at 11 checkpoints *inside* the run. | model chosen by validation | validation PR-AUC | test PR-AUC | precision on test | |---|---|---|---| | ch64, kernel 5, 3 dilations | 0.3661 | 0.2284 | 26.0% | | best on test instead | 0.3661 | 0.2284 | 26.0% | Against blind picking on the test period (3.6%) that is a real signal — roughly 7.3 times better than chance. And here is the uncomfortable part. **Validation does not rank the models.** Among the three finalists the ordering on test is close to the reverse of the ordering on validation. The reason is visible in the numbers: the test chunks landed on a quiet stretch of the market with 3.6% reversals, while validation had 13.8%. With 200 reversals in the test set, PR-AUC is too noisy to choose an architecture with. We are reporting this rather than quietly picking the best number, because a bot built on "the architecture that won validation" would be built on a coin flip. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. A model we cannot rank honestly is a model we cannot deploy. ## ③ What the pool splits into on its own Now the same pool, but without any labels at all: PCA → UMAP → HDBSCAN, and our reversal marks applied only afterwards, as a check. The split is real — stability 0.813 on a full rebuild with a different seed, against 0.378 for a hard null where the cells are shuffled between events. But it is **not about reversals** (ARI 0.026) and not about our three classes (ARI 0.038). It cuts the pool along something else entirely: the level of the flows. | class | events | reversals inside | versus the pool average | |---|---|---|---| | noise | 43,719 | 6.1% | ×0.91 | | class 0 | 2,663 | 2.4% | ×0.36 | | class 1 | 1,093 | 9.2% | ×1.36 | | class 2 | 7,203 | 12.4% | ×1.85 | | class 3 | 1,251 | 2.0% | ×0.30 | The most reversal-rich class carries them at ×1.85 the base rate, the wall-shaped ones at a third of it. So reversals are **shifted** by the structure of the book, never **isolated** by it — the fourth time this series arrives at that sentence by a different road. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. A shift of ×1.85 is not a trade on its own, but it is a filter: it tells a bot which events are worth spending a second signal on. ## ④ Every compression lost to one average Last question of this study: does the event need to be *compressed* before the model sees it? We ran PCA and an autoencoder at five bottleneck widths, with the same logistic head on top of both, so that what is compared is the compression and not the head. | what we compressed with | best width | validation PR-AUC | test PR-AUC | |---|---|---|---| | PCA | 64 | 0.2253 | 0.0685 | | autoencoder | 64 | 0.2283 | 0.0713 | | autoencoder as an anomaly score | 64 | 0.2818 | 0.0891 | | **one number: the mean level of the six flow features** | — | **0.3137** | **0.1156** | Both compressions lost to a single average, and the full network on all 1,680 numbers beat every bottleneck by a factor of two. The autoencoder as an *anomaly* detector — trained only on non-reversals, scored by reconstruction error — was the weakest of the three, and that is a finding rather than a failure: a reversal is not anomalous for a model that has learned ordinary events. It reconstructs just fine. It is simply louder. **What is next.** The following studies stop asking the model to be clever and start asking the data to be clean: what the whole dataset splits into when nobody tells it what to look for, how that split behaves in the rising and the falling half of a move, whether it reproduces week by week — and finally how to throw away the part of the data that carries no reversals at all. Everything in this series feeds one goal: an automated trading bot that reads the order book instead of the price. Every one of those steps is about giving that bot fewer, better events to look at. ================================================================================ # Three Classes, One Question: What It Takes to Separate a Reversal URL: https://marketflowresear.ch/articles/three-classes-one-question-what-it-takes-to-separate-a-reversal/ Published: 2026-08-13 · Series: Order-book research · Separating the signal > Three market states, one question: can an order-book event that sits on a turning point be told apart from the ordinary events of its own class? This is the overview of that work — the three per-class studies side by side, every engine we tried in between, and the parts that hurt: a grid search that bought 0.02 AUC, a network on 1,680 numbers that lost to a single average, and a threshold that looked like 63% precision until it was asked to survive two months of new data, where it became 39%. ## ① Three classes and the ruler that makes them comparable The point of all of this is not a leaderboard. A trading bot needs one thing from research: a moment when the book says *something is about to change* with enough purity that a position taken on it survives the 0.30% round-trip fee. Everything below is an attempt to isolate that moment inside one market state at a time. Every window in this study is the same object: **210 seconds × 8 order-book features**, one number per feature per second, and nothing else — no price, no time of day, no neighbouring windows. The label comes from an earlier study on this dataset: signals of a class merge into a **group** while the gap between them is under 10 minutes, and a group counts as a **reversal** if it touches a ZigZag pivot on the 2.3% grid within ±15 minutes. The label belongs to the group and is inherited by its windows. The test is **a random 10% of the events**, held out and touched exactly once; of the rest, 15% is the validation set on which every choice is made. The network and all of its parameters are frozen for every class and every feature set — 64 channels, kernel 3, dilations 1-2-4-8-16-32, weight decay 1e-3, 16 epochs — because otherwise a comparison between classes would be measuring the parameter search, not the class. Three classes carry enough reversals to train on. The fourth — the PCA-quiet pole — has **one** reversal window in 4,598, so it is out of this study by arithmetic, not by choice. | class | windows | base rate | best set | precision | recall | AUC | vs base | |---|---|---|---|---|---|---|---| | storm | 5,249 | 20.7% | 5 features | 54.1% | 50.0% | 0.771 | ×2.6 | | calm | 29,303 | 2.5% | 8 features | 14.9% | 15.3% | 0.785 | ×6.0 | | class 2 | 21,704 | 9.0% | 6 features | 23.5% | 23.6% | 0.697 | ×2.6 | **The chart above is why that table needs two panels.** On the left, precision and base rate side by side: storm looks like the best class by a wide margin. On the right, the same result divided by each class's own base rate — and the order changes. Calm, the class whose absolute numbers look weakest, turns out to be the one where the model beats blind picking by the largest factor, because reversals there are rare and genuinely unlike the rest of their class. Storm's high precision is mostly a high base rate: one in five storm events is a reversal to begin with. For a bot the two panels answer different questions. The left one says how dirty the signal stream will be. The right one says how much the model actually knows. ## ② Everything we tried, and what it cost Before the per-class work, the same question was attacked head-on inside the storm class, with everything we had. This is the part worth reading if you are deciding whether to spend a week on architecture. | engine | AUC | null control | |---|---|---| | nearest centroid, 1260 numbers | 0.691 | — | | boosting, 30 descriptors | 0.678 | 0.459 | | logistic regression, 8 levels | 0.656 | 0.511 | | dilated CNN, all 8 features | 0.649 | 0.460 | | boosting, 1260 raw numbers | 0.657 | 0.469 | Blocked folds in time with a 30-minute embargo; the null control is the same engine trained on a cyclically shifted label. **Read the bar chart from the bottom up.** The null control sits at 0.460 — below 0.5, because a shifted label is not a fair coin. Above it, everything else lands in a band barely 0.05 wide. The dilated network on all eight features, the one that took the longest to train, is *not* at the top. The top is a nearest centroid: compute the average reversal vector, compute the average ordinary vector, and ask which one a new event is closer to. Three specific attempts hurt more than the others: **The grid search.** 60 architectures × 7 epoch checkpoints × 3 weight decays × 2 learning rates on one feature. The winner reached 0.682 AUC and 44.0% precision on the untouched test. A logistic regression on that same feature's **single average level** reached 0.661 and 38.5%. The entire search bought about 0.02 AUC, and the spread across all 60 architectures was 0.050 PR-AUC — less than the difference between two random splits. **More features made it worse.** With one network per feature on blocked folds, `resist_plus` alone reached 0.677 AUC — *higher* than all eight features together (0.649). And `const_resist` reached 0.504 against a null of 0.501, which is to say nothing at all: the walls do not move at a reversal, so 210 of the network's input columns were pure noise. **Longer training made it worse.** Sampling one training run at 14 checkpoints from 2 to 256 epochs: the peak is at 16 epochs (0.689 AUC on unseen windows), and by 256 epochs the model scores 0.620 on unseen data while climbing to 0.760 on the windows it was trained on. That is the textbook picture of overfitting, arriving after 16 epochs on 5,249 examples. ## ③ The threshold that did not survive time Here is the part that decides whether any of this can be automated. Take the best single-feature model and stop using the calibrated threshold. Take only the most confident answers instead — the top 0.5%, the top 1%, the top 5% — and precision climbs exactly as it should: **63.0%** at the top 0.5%, 52.8% at the top 1%, against a base rate of 20.7%. Then take that same threshold, compute it on the **first 60% of the timeline**, and apply it to the remaining 40% — which is what a live bot does by definition, because it cannot calibrate on data it has not seen yet. | we take | precision when the threshold is fitted on the same data | precision when it comes from the first 60% of time | |---|---|---| | top 0.5% | 63.0% | 39.3% on 392 firings | | top 1% | 52.8% | 39.0% on 485 firings | | top 2% | 51.4% | 37.6% on 595 firings | | top 5% | 44.1% | 35.1% on 793 firings | | top 10% | 40.0% | 32.8% on 989 firings | | top 20.67% | 35.8% | 31.4% on 1,161 firings | **The bar chart shows the two columns as pairs.** Orange is the optimistic number, blue is the honest one, the green line is the base rate. The gap is not overfitting in the usual sense — the model is the same model. What moves is the *distribution of its answers*: a score that was in the top 0.5% of the training period is in the top 8% of the next one, so the same numeric threshold fires 15 times more often and drags in everything ordinary. That is the practical ceiling of this line as it stands: **about 39.3% precision from a frozen threshold**, against a base rate of 20.7%. Not zero — roughly twice blind picking — but nowhere near the 63% the optimistic column promises. ## ④ The pain, and what is left standing **What holds up.** A reversal event is real and it is visible in the book. In all three classes the same signature appears — the inflow into both walls rises while the walls themselves stay put — and in all three classes a frozen network separates reversals from the ordinary events of their own class better than blind picking: ×2.6, ×6.0, ×2.6. The per-feature ranking differs by class, and that difference is itself a finding: storm is carried by volume, calm needs all eight features, class 2 has no leader at all. **What does not.** Everything expensive. The grid search bought 0.02 AUC over a single average. The full 1,680-number input lost to one feature. Longer training made it worse after 16 epochs. And the strict threshold — the one operating point a bot would actually use — lost 40% of its precision the moment it had to survive unseen time. **The pain, stated plainly.** The bottleneck in this work was never the model; it was that a reversal is not a different *kind* of event but the loud end of an ordinary one. Every method that assumes two categories — a classifier, a centroid, a threshold — is being asked to cut a continuum, and it cuts it at whatever level the recent past happened to have. That is why the between-class comparison had to be rebuilt around one common ruler (precision ÷ base rate) instead of raw precision, why the calm class turned out to be the strongest despite the worst-looking numbers, and why the honest threshold column is the only one we would hand to an automated system. **What this is worth for a bot.** One usable rule, and it is a modest one: inside a class, the top few percent of the model's answers carry reversals at roughly twice the class's own rate, and that ratio survives an honest split in time. On its own that does not clear a 0.30% round-trip fee. It becomes interesting only in intersection — with a second, independent signal, or with a class rare enough that twice its base rate is already a tradeable purity. Both of those are the next studies, and both are now specified precisely enough to run. The three per-class studies, with every table and chart behind the numbers above: - [Storm reversals](https://marketflowresear.ch/articles/the-storm-class-which-order-book-feature-marks-a-reversal/) — the loudest class, carried by volume - [Calm reversals](https://marketflowresear.ch/articles/reversals-in-a-quiet-market-where-two-percent-of-events-hide/) — the rarest reversals, and the largest advantage over chance - [Class 2 reversals](https://marketflowresear.ch/articles/class-2-the-middle-state-where-no-single-feature-wins/) — the middle state, where no single feature wins ================================================================================ # Class 2: the Middle State Where No Single Feature Wins URL: https://marketflowresear.ch/articles/class-2-the-middle-state-where-no-single-feature-wins/ Published: 2026-08-13 · Series: Order-book research · Class 2 reversals > The class 2 state fires on 21,704 windows of this dataset, and 1,961 of them (9.0%) sit on a turning point of price. This page asks one question and answers it with one frozen network: can a reversal be told apart from the ordinary events of its own class, and which of the eight order-book features carries that difference? Best single feature: vol_buy at 15.8% precision. Best set: 6 features at 23.5% precision and 23.6% recall, against a base rate of 9.0% — ×2.6. ## ① What a reversal looks like inside the class 2 class The point of all of this is not a leaderboard. A trading bot needs one thing from research: a moment when the book says *something is about to change* with enough purity that a position taken on it survives the 0.30% round-trip fee. Everything below is an attempt to isolate that moment inside one market state at a time. Every window in this study is the same object: **210 seconds × 8 order-book features**, one number per feature per second, and nothing else — no price, no time of day, no neighbouring windows. The label comes from an earlier study on this dataset: signals of a class merge into a **group** while the gap between them is under 10 minutes, and a group counts as a **reversal** if it touches a ZigZag pivot on the 2.3% grid within ±15 minutes. The label belongs to the group and is inherited by its windows. Inside the **class 2** class that gives 21,704 windows, of which 1,961 are reversal windows — a base rate of **9.0%**. Everything on this page is measured against that number: a model that fires blindly would be right 9.0% of the time. **The heat map above is the whole problem in one image.** It is the reversal windows of this class minus the same class *without* its reversals, cell by cell: eight feature rows, 210 second-columns, raw units, red where a reversal runs hotter than an ordinary event of the same class and blue where it runs colder. The scale is shared with the other two classes so the images can be laid side by side. Read it row by row rather than as a picture. In class 2 the map is the faintest of the three, and the difference is spread thinly across rows instead of concentrating in one or two. The uniformity along the horizontal axis matters more than it looks. It says the information is in the **level** of a feature during the window, not in the *shape* of its curve — no ramp, no spike, no ordering of seconds. That single observation is what makes the rest of this page possible: if the answer is a level, then a network fed one feature at a time should already see most of it. | feature | ordinary events | reversals | ratio | |---|---|---|---| | `vol_sell` | 0.088 | 0.101 | ×1.15 | | `vol_buy` | 0.089 | 0.098 | ×1.10 | | `resist_plus` | 2.352 | 2.576 | ×1.10 | | `support_plus` | 2.204 | 2.410 | ×1.09 | | `resist_minus` | 0.911 | 0.976 | ×1.07 | | `support_minus` | 0.880 | 0.928 | ×1.05 | | `const_support` | 1.627 | 1.496 | ×0.92 | | `const_resist` | 1.745 | 1.586 | ×0.91 | Top movers: `vol_sell` ×1.15, `vol_buy` ×1.10, `resist_plus` ×1.10. ## ② One network per feature If the signal is a level, the cleanest way to find out *whose* level it is to give the network one feature and nothing else: an input of exactly 210 numbers, the same frozen architecture, the same split, eight separate models. | feature | precision | recall | AUC | vs base | |---|---|---|---|---| | `vol_buy` | 15.8% | 15.9% | 0.622 | ×1.8 | | `resist_plus` | 15.3% | 15.4% | 0.628 | ×1.7 | | `vol_sell` | 15.3% | 15.4% | 0.640 | ×1.7 | | `resist_minus` | 14.3% | 14.4% | 0.600 | ×1.6 | | `support_minus` | 14.3% | 14.4% | 0.616 | ×1.6 | | `const_support` | 13.8% | 13.9% | 0.644 | ×1.5 | | `const_resist` | 13.3% | 13.3% | 0.587 | ×1.5 | | `support_plus` | 12.2% | 12.3% | 0.619 | ×1.4 | Base rate 9.0%; the threshold is set so that the number of firings equals the number of reversals, which is why precision and recall coincide — both count the same hits in different denominators. **How to read the bar chart.** Three bars per feature: precision (orange), recall (blue), AUC (grey), features sorted by precision. The green dashed line is the base rate — the level a coin flip weighted to the right frequency would reach. AUC has its own reference: the dotted line at 0.5. A feature is interesting when its orange bar clears the green line and its grey bar clears the dotted one. `vol_buy` leads at 15.8% precision and 0.622 AUC. `support_plus` sits last at 12.2%. The eight features sit within a few points of each other, and the AUC column is even flatter — between 0.587 and 0.644. No feature owns this class. Note what the AUC column does *not* do: it does not follow precision. A feature can order the whole list well and still fail at the top of it, which is the only part a bot would ever act on. ## ③ Adding one feature at a time One feature at a time answers *who*, not *how much together*. So the sets are grown greedily: start from the best single feature, then at every round try each remaining feature as an extra input channel and keep the one that raises precision on the validation set. The test set never participates in the choice; it is measured once per round. Architecture and parameters stay frozen throughout, so every point on the curve differs only by which features are on the input. | features | added | precision | recall | AUC | |---|---|---|---|---| | 1 | `vol_buy` | 15.8% | 15.9% | 0.622 | | 2 | `support_minus` | 17.9% | 17.9% | 0.609 | | 3 | `resist_plus` | 18.4% | 18.5% | 0.651 | | 4 | `const_resist` | 20.4% | 20.5% | 0.638 | | 5 | `const_support` | 18.9% | 19.0% | 0.684 | | 6 | `vol_sell` **←** | 23.5% | 23.6% | 0.697 | | 7 | `resist_minus` | 20.9% | 21.0% | 0.696 | | 8 | `support_plus` | 18.9% | 19.0% | 0.660 | **How to read the curve.** The horizontal axis is the order in which features entered, not their importance — each label says what was added at that step. Orange is precision, blue recall, grey AUC; the green dashed line is the base rate; the vertical dashed line marks the best step. Class 2 climbs slowly to its best at 6 features and then falls back. It is the middle state in every sense: neither one loud feature nor a clean accumulation. The best set on this class: **6 features** — `vol_buy`, `support_minus`, `resist_plus`, `const_resist`, `const_support`, `vol_sell` — at 23.5% precision, 23.6% recall, AUC 0.697. ## ④ What this class hands to a trading bot Put the two views together. On a test of 2,170 events the model fires about 196 times, and 23.5% of those firings are real reversals. In counts: roughly 46 hits, 150 false alarms, and about 150 reversals missed in silence. That is the shape of what a bot would actually receive from this class — not a verdict, a rate. Three things constrain how far it can be pushed, and all three are visible in the numbers on this page rather than argued from theory: **The split flatters us.** It is random, so a neighbouring 210-second window of the same event is almost always in training. On the blocked-in-time split used elsewhere in this line, the same task on the same class lands several points lower, and the null control — the same network trained on a cyclically shifted label — reaches 0.460 AUC instead of 0.500. Numbers from the two splits must never be compared. **The level is the signal, and levels drift.** The ratios in the first table are the whole mechanism: `vol_sell` ×1.15, `vol_buy` ×1.10. A threshold calibrated on one stretch of history fires at a different rate on the next one, which is a separate problem from accuracy and is measured in the overview article. **Precision is bounded by the base rate.** At 9.0% of events being reversals, even a strong ranking leaves most of the top of the list wrong. The lever is not a better architecture — it is a class whose events are rarer and cleaner, or a second, independent signal to intersect with this one. This page deliberately stops at the numbers and states no verdict. The verdict needs all three classes next to each other, and it lives in the overview: - [Storm reversals](https://marketflowresear.ch/articles/the-storm-class-which-order-book-feature-marks-a-reversal/) — the same question inside the **storm** class - [Calm reversals](https://marketflowresear.ch/articles/reversals-in-a-quiet-market-where-two-percent-of-events-hide/) — the same question inside the **calm** class - [Separating the signal](https://marketflowresear.ch/articles/three-classes-one-question-what-it-takes-to-separate-a-reversal/) — all three classes side by side, everything we tried in between, and what this is worth for an automated system ================================================================================ # Reversals in a Quiet Market: Where 2.5% of Events Hide URL: https://marketflowresear.ch/articles/reversals-in-a-quiet-market-where-two-percent-of-events-hide/ Published: 2026-08-13 · Series: Order-book research · Calm reversals > The calm state fires on 29,303 windows of this dataset, and 739 of them (2.5%) sit on a turning point of price. This page asks one question and answers it with one frozen network: can a reversal be told apart from the ordinary events of its own class, and which of the eight order-book features carries that difference? Best single feature: vol_buy at 10.8% precision. Best set: 8 features at 14.9% precision and 15.3% recall, against a base rate of 2.5% — ×6.0. ## ① What a reversal looks like inside the calm class The point of all of this is not a leaderboard. A trading bot needs one thing from research: a moment when the book says *something is about to change* with enough purity that a position taken on it survives the 0.30% round-trip fee. Everything below is an attempt to isolate that moment inside one market state at a time. Every window in this study is the same object: **210 seconds × 8 order-book features**, one number per feature per second, and nothing else — no price, no time of day, no neighbouring windows. The label comes from an earlier study on this dataset: signals of a class merge into a **group** while the gap between them is under 10 minutes, and a group counts as a **reversal** if it touches a ZigZag pivot on the 2.3% grid within ±15 minutes. The label belongs to the group and is inherited by its windows. Inside the **calm** class that gives 29,303 windows, of which 739 are reversal windows — a base rate of **2.5%**. Everything on this page is measured against that number: a model that fires blindly would be right 2.5% of the time. **The heat map above is the whole problem in one image.** It is the reversal windows of this class minus the same class *without* its reversals, cell by cell: eight feature rows, 210 second-columns, raw units, red where a reversal runs hotter than an ordinary event of the same class and blue where it runs colder. The scale is shared with the other two classes so the images can be laid side by side. Read it row by row rather than as a picture. In the calm class the whole map is fainter, which is exactly what one would expect from a state defined by low flows — but the same two inflow rows are the ones that lift, and they lift uniformly along the window. The uniformity along the horizontal axis matters more than it looks. It says the information is in the **level** of a feature during the window, not in the *shape* of its curve — no ramp, no spike, no ordering of seconds. That single observation is what makes the rest of this page possible: if the answer is a level, then a network fed one feature at a time should already see most of it. | feature | ordinary events | reversals | ratio | |---|---|---|---| | `support_plus` | 2.155 | 3.362 | ×1.56 | | `resist_plus` | 2.346 | 3.554 | ×1.52 | | `support_minus` | 0.908 | 1.367 | ×1.51 | | `resist_minus` | 0.962 | 1.356 | ×1.41 | | `vol_sell` | 0.067 | 0.094 | ×1.41 | | `vol_buy` | 0.065 | 0.089 | ×1.36 | | `const_resist` | 3.165 | 3.265 | ×1.03 | | `const_support` | 3.115 | 3.090 | ×0.99 | Top movers: `support_plus` ×1.56, `resist_plus` ×1.52, `support_minus` ×1.51. ## ② One network per feature If the signal is a level, the cleanest way to find out *whose* level it is to give the network one feature and nothing else: an input of exactly 210 numbers, the same frozen architecture, the same split, eight separate models. | feature | precision | recall | AUC | vs base | |---|---|---|---|---| | `vol_buy` | 10.8% | 11.1% | 0.758 | ×4.3 | | `support_minus` | 8.1% | 8.3% | 0.703 | ×3.2 | | `vol_sell` | 8.1% | 8.3% | 0.719 | ×3.2 | | `const_resist` | 5.4% | 5.6% | 0.623 | ×2.2 | | `const_support` | 5.4% | 5.6% | 0.725 | ×2.2 | | `resist_plus` | 4.0% | 4.2% | 0.713 | ×1.6 | | `support_plus` | 4.0% | 4.2% | 0.683 | ×1.6 | | `resist_minus` | 2.7% | 2.8% | 0.724 | ×1.1 | Base rate 2.5%; the threshold is set so that the number of firings equals the number of reversals, which is why precision and recall coincide — both count the same hits in different denominators. **How to read the bar chart.** Three bars per feature: precision (orange), recall (blue), AUC (grey), features sorted by precision. The green dashed line is the base rate — the level a coin flip weighted to the right frequency would reach. AUC has its own reference: the dotted line at 0.5. A feature is interesting when its orange bar clears the green line and its grey bar clears the dotted one. `vol_buy` leads at 10.8% precision and 0.758 AUC. `resist_minus` sits last at 2.7%. Every feature clears the base rate here, which sounds encouraging until you notice how low that base is — 2.5% means the leader is right one time in ten. Note what the AUC column does *not* do: it does not follow precision. A feature can order the whole list well and still fail at the top of it, which is the only part a bot would ever act on. ## ③ Adding one feature at a time One feature at a time answers *who*, not *how much together*. So the sets are grown greedily: start from the best single feature, then at every round try each remaining feature as an extra input channel and keep the one that raises precision on the validation set. The test set never participates in the choice; it is measured once per round. Architecture and parameters stay frozen throughout, so every point on the curve differs only by which features are on the input. | features | added | precision | recall | AUC | |---|---|---|---|---| | 1 | `support_plus` | 4.0% | 4.2% | 0.683 | | 2 | `vol_sell` | 5.4% | 5.6% | 0.700 | | 3 | `vol_buy` | 9.5% | 9.7% | 0.743 | | 4 | `support_minus` | 6.8% | 6.9% | 0.765 | | 5 | `const_resist` | 6.8% | 6.9% | 0.725 | | 6 | `resist_minus` | 6.8% | 6.9% | 0.772 | | 7 | `const_support` | 12.2% | 12.5% | 0.779 | | 8 | `resist_plus` **←** | 14.9% | 15.3% | 0.785 | **How to read the curve.** The horizontal axis is the order in which features entered, not their importance — each label says what was added at that step. Orange is precision, blue recall, grey AUC; the green dashed line is the base rate; the vertical dashed line marks the best step. Calm behaves the opposite way: no single feature carries it, and the curve keeps climbing until all eight are in. AUC rises almost monotonically — 0.683 at the start, 0.785 at the end. In a quiet market the difference is smeared across the whole book, and you need the whole book to see it. The best set on this class: **8 features** — `support_plus`, `vol_sell`, `vol_buy`, `support_minus`, `const_resist`, `resist_minus`, `const_support`, `resist_plus` — at 14.9% precision, 15.3% recall, AUC 0.785. ## ④ What this class hands to a trading bot Put the two views together. On a test of 2,930 events the model fires about 73 times, and 14.9% of those firings are real reversals. In counts: roughly 11 hits, 62 false alarms, and about 63 reversals missed in silence. That is the shape of what a bot would actually receive from this class — not a verdict, a rate. Three things constrain how far it can be pushed, and all three are visible in the numbers on this page rather than argued from theory: **The split flatters us.** It is random, so a neighbouring 210-second window of the same event is almost always in training. On the blocked-in-time split used elsewhere in this line, the same task on the same class lands several points lower, and the null control — the same network trained on a cyclically shifted label — reaches 0.460 AUC instead of 0.500. Numbers from the two splits must never be compared. **The level is the signal, and levels drift.** The ratios in the first table are the whole mechanism: `support_plus` ×1.56, `resist_plus` ×1.52. A threshold calibrated on one stretch of history fires at a different rate on the next one, which is a separate problem from accuracy and is measured in the overview article. **Precision is bounded by the base rate.** At 2.5% of events being reversals, even a strong ranking leaves most of the top of the list wrong. The lever is not a better architecture — it is a class whose events are rarer and cleaner, or a second, independent signal to intersect with this one. This page deliberately stops at the numbers and states no verdict. The verdict needs all three classes next to each other, and it lives in the overview: - [Storm reversals](https://marketflowresear.ch/articles/the-storm-class-which-order-book-feature-marks-a-reversal/) — the same question inside the **storm** class - [Class 2 reversals](https://marketflowresear.ch/articles/class-2-the-middle-state-where-no-single-feature-wins/) — the same question inside the **class 2** class - [Separating the signal](https://marketflowresear.ch/articles/three-classes-one-question-what-it-takes-to-separate-a-reversal/) — all three classes side by side, everything we tried in between, and what this is worth for an automated system ================================================================================ # The Storm Class: Which Order-Book Feature Marks a Reversal URL: https://marketflowresear.ch/articles/the-storm-class-which-order-book-feature-marks-a-reversal/ Published: 2026-08-13 · Series: Order-book research · Storm reversals > The storm state fires on 5,249 windows of this dataset, and 1,085 of them (20.7%) sit on a turning point of price. This page asks one question and answers it with one frozen network: can a reversal be told apart from the ordinary events of its own class, and which of the eight order-book features carries that difference? Best single feature: vol_buy at 49.5% precision. Best set: 5 features at 54.1% precision and 50.0% recall, against a base rate of 20.7% — ×2.6. ## ① What a reversal looks like inside the storm class The point of all of this is not a leaderboard. A trading bot needs one thing from research: a moment when the book says *something is about to change* with enough purity that a position taken on it survives the 0.30% round-trip fee. Everything below is an attempt to isolate that moment inside one market state at a time. Every window in this study is the same object: **210 seconds × 8 order-book features**, one number per feature per second, and nothing else — no price, no time of day, no neighbouring windows. The label comes from an earlier study on this dataset: signals of a class merge into a **group** while the gap between them is under 10 minutes, and a group counts as a **reversal** if it touches a ZigZag pivot on the 2.3% grid within ±15 minutes. The label belongs to the group and is inherited by its windows. Inside the **storm** class that gives 5,249 windows, of which 1,085 are reversal windows — a base rate of **20.7%**. Everything on this page is measured against that number: a model that fires blindly would be right 20.7% of the time. **The heat map above is the whole problem in one image.** It is the reversal windows of this class minus the same class *without* its reversals, cell by cell: eight feature rows, 210 second-columns, raw units, red where a reversal runs hotter than an ordinary event of the same class and blue where it runs colder. The scale is shared with the other two classes so the images can be laid side by side. Read it row by row rather than as a picture. In the storm the two inflow rows — `resist_plus` and `support_plus` — are solid red across the entire width, with no build-up and no decay: a reversal is not a moment inside the window, it is a level the whole window sits at. The two `const` wall rows are flat and almost white, and the volume rows are barely tinted — in raw units they live at 0.35 while the inflows live at 8.9, so the same relative move produces a fainter colour. The uniformity along the horizontal axis matters more than it looks. It says the information is in the **level** of a feature during the window, not in the *shape* of its curve — no ramp, no spike, no ordering of seconds. That single observation is what makes the rest of this page possible: if the answer is a level, then a network fed one feature at a time should already see most of it. | feature | ordinary events | reversals | ratio | |---|---|---|---| | `resist_plus` | 8.181 | 11.422 | ×1.40 | | `support_plus` | 7.911 | 10.963 | ×1.39 | | `resist_minus` | 3.240 | 4.302 | ×1.33 | | `support_minus` | 3.233 | 4.104 | ×1.27 | | `vol_buy` | 0.335 | 0.413 | ×1.23 | | `vol_sell` | 0.351 | 0.407 | ×1.16 | | `const_resist` | 2.542 | 2.495 | ×0.98 | | `const_support` | 2.675 | 2.398 | ×0.90 | Top movers: `resist_plus` ×1.40, `support_plus` ×1.39, `resist_minus` ×1.33. ## ② One network per feature If the signal is a level, the cleanest way to find out *whose* level it is to give the network one feature and nothing else: an input of exactly 210 numbers, the same frozen architecture, the same split, eight separate models. | feature | precision | recall | AUC | vs base | |---|---|---|---|---| | `vol_buy` | 49.5% | 45.8% | 0.785 | ×2.4 | | `const_resist` | 43.1% | 39.8% | 0.676 | ×2.1 | | `resist_minus` | 43.1% | 39.8% | 0.685 | ×2.1 | | `resist_plus` | 42.2% | 39.0% | 0.683 | ×2.0 | | `vol_sell` | 41.3% | 38.1% | 0.702 | ×2.0 | | `support_minus` | 39.5% | 36.4% | 0.684 | ×1.9 | | `support_plus` | 37.6% | 34.8% | 0.674 | ×1.8 | | `const_support` | 26.6% | 24.6% | 0.601 | ×1.3 | Base rate 20.7%; the threshold is set so that the number of firings equals the number of reversals, which is why precision and recall coincide — both count the same hits in different denominators. **How to read the bar chart.** Three bars per feature: precision (orange), recall (blue), AUC (grey), features sorted by precision. The green dashed line is the base rate — the level a coin flip weighted to the right frequency would reach. AUC has its own reference: the dotted line at 0.5. A feature is interesting when its orange bar clears the green line and its grey bar clears the dotted one. `vol_buy` leads at 49.5% precision and 0.785 AUC. `const_support` sits last at 26.6%. The gap between the leader and the field is the largest of the three classes, and it belongs to volume rather than to the book: in a storm, trades carry the turn. Note what the AUC column does *not* do: it does not follow precision. A feature can order the whole list well and still fail at the top of it, which is the only part a bot would ever act on. ## ③ Adding one feature at a time One feature at a time answers *who*, not *how much together*. So the sets are grown greedily: start from the best single feature, then at every round try each remaining feature as an extra input channel and keep the one that raises precision on the validation set. The test set never participates in the choice; it is measured once per round. Architecture and parameters stay frozen throughout, so every point on the curve differs only by which features are on the input. | features | added | precision | recall | AUC | |---|---|---|---|---| | 1 | `vol_buy` | 49.5% | 45.8% | 0.785 | | 2 | `vol_sell` | 51.4% | 47.5% | 0.773 | | 3 | `support_plus` | 48.6% | 44.9% | 0.761 | | 4 | `const_resist` | 45.0% | 41.5% | 0.754 | | 5 | `resist_minus` **←** | 54.1% | 50.0% | 0.771 | | 6 | `resist_plus` | 39.5% | 36.4% | 0.704 | | 7 | `const_support` | 52.3% | 48.3% | 0.764 | | 8 | `support_minus` | 42.2% | 39.0% | 0.746 | **How to read the curve.** The horizontal axis is the order in which features entered, not their importance — each label says what was added at that step. Orange is precision, blue recall, grey AUC; the green dashed line is the base rate; the vertical dashed line marks the best step. Storm peaks early and then wobbles: the pair of volumes already carries most of it, and the later steps move up and down by amounts that a test of 525 events cannot resolve — one step of the table is about five events. The honest reading is that storm needs two to five features and that anything beyond that is noise, not improvement. The best set on this class: **5 features** — `vol_buy`, `vol_sell`, `support_plus`, `const_resist`, `resist_minus` — at 54.1% precision, 50.0% recall, AUC 0.771. ## ④ What this class hands to a trading bot Put the two views together. On a test of 525 events the model fires about 109 times, and 54.1% of those firings are real reversals. In counts: roughly 59 hits, 50 false alarms, and about 54 reversals missed in silence. That is the shape of what a bot would actually receive from this class — not a verdict, a rate. Three things constrain how far it can be pushed, and all three are visible in the numbers on this page rather than argued from theory: **The split flatters us.** It is random, so a neighbouring 210-second window of the same event is almost always in training. On the blocked-in-time split used elsewhere in this line, the same task on the same class lands several points lower, and the null control — the same network trained on a cyclically shifted label — reaches 0.460 AUC instead of 0.500. Numbers from the two splits must never be compared. **The level is the signal, and levels drift.** The ratios in the first table are the whole mechanism: `resist_plus` ×1.40, `support_plus` ×1.39. A threshold calibrated on one stretch of history fires at a different rate on the next one, which is a separate problem from accuracy and is measured in the overview article. **Precision is bounded by the base rate.** At 20.7% of events being reversals, even a strong ranking leaves most of the top of the list wrong. The lever is not a better architecture — it is a class whose events are rarer and cleaner, or a second, independent signal to intersect with this one. This page deliberately stops at the numbers and states no verdict. The verdict needs all three classes next to each other, and it lives in the overview: - [Calm reversals](https://marketflowresear.ch/articles/reversals-in-a-quiet-market-where-two-percent-of-events-hide/) — the same question inside the **calm** class - [Class 2 reversals](https://marketflowresear.ch/articles/class-2-the-middle-state-where-no-single-feature-wins/) — the same question inside the **class 2** class - [Separating the signal](https://marketflowresear.ch/articles/three-classes-one-question-what-it-takes-to-separate-a-reversal/) — all three classes side by side, everything we tried in between, and what this is worth for an automated system ================================================================================ # We Went Looking for the DNA of a Reversal. We Found a Ceiling Instead. URL: https://marketflowresear.ch/articles/we-went-looking-for-the-dna-of-a-reversal-we-found-a-ceiling-instead/ Published: 2026-08-12 · Series: Order-book research · Reversal DNA > An earlier study on this dataset (175 days of BTC) found 271 order-book events that sit exactly on the turning points of price, and showed that a model cannot separate them from the thousands of ordinary events of their own class. This study asks a narrower question: forget separating a reversal from its class — is there anything, on its own, that a reversal event's 271 examples share? Nine different methods attack the question from nine angles: a two-condition threshold rule, a raw-vector kinship check, a full neural detector, a scan for the shortest useful slice of the window, four models on four quarters of it, one model on all of its 30-second slices at once, and three independent models — one per parent market state. Every method finds something real, reproducible, and well above every null control we built. None of them clears the bar a trading signal needs. The best operating point we found, buried inside the loudest of four market states, is right roughly one time in three. ## ① What we are looking for, and why it is a different question The predecessor study, [We Found the Reversal Signal. Machine Learning Could Not Tell It Apart](/articles/we-found-the-reversal-signal-machine-learning-could-not-tell-it-apart/), took four detectors trained on this dataset — storm, class 2, calm and PCA-quiet, from [an earlier study](/articles/four-market-states-found-twice-by-two-independent-pipelines/) — and found 271 groups of their firings that sit on a turning point of price (ZigZag 2.3%, ±15 minutes). It then asked models to separate those 271 events from the *rest of their own class*, and failed: at the window level, nothing beat a null control. This study drops the "of their own class" clause. The question becomes simpler and cheaper to ask: do the 271 reversal events, taken together, look like anything at all — a compact rule, a kinship with each other, a signature a network can find against the *whole* dataset rather than only against their own class's other firings? Nine methods answer this from nine directions, in order of increasing model capacity: a two-condition threshold rule · a raw-vector similarity check · a full neural detector on the whole 210-second window · a scan for whether a shorter slice of the window is enough · four separate models on four quarters of it · one model trained on all of its 30-second slices at once · and, last, three independent models, one per parent market state. Every method is graded against the same discipline this project uses everywhere models train on time series: a chronological, group-blocked split with an embargo, so that no window near a reversal a model has already seen leaks into its own test fold. All numbers below are out-of-fold. ## ② The cheapest hypothesis first: a two-condition rule Before training anything, we asked the simplest possible question in the style this project uses for its live rules elsewhere on the dashboard: is there a 1–2-condition AND rule on 11 group-level numbers (8 average feature levels, group size, duration, sharpness) that separates a class's reversal groups from the rest of its own firings? Top features by |AUC−0.5|, a grid of thresholds, F1 maximised on the first 70% of groups by time, checked on the last 30%. | class | rule | holdout precision / recall | base rate | lift | |---|---|---|---|---| | storm | `dur_min ≥ 35` | 0.275 / 0.44 | 0.0676 | ×4.07 | | class 2 | `vol_buy ≥ 0.928 AND support_plus ≥ 3.49` | 0.018 / 0.091 | 0.0217 | ×0.85 | | calm | `support_minus ≥ 3.86` | 0.084 / 0.545 | 0.0341 | ×2.46 | Class 2's rule looks reasonable on the 71 groups it was fit to and then scores *below* its own base rate out of sample — lift 0.85, worse than a coin flip. Storm's rule, the best of the three, holds up better (×4.07) but still means three out of every four times it fires, it is wrong. We are not showing this as a failed idea to discard — this result, applied to *every* group in the dataset, is the honest floor the rest of the study measures itself against. ## ③ Are the 271 events even related to each other? A cheaper check than training anything: are the 3734 windows that make up the 271 events more similar to each other than to a random window? Every window becomes a 1680-number vector, standardised against the population and scaled to unit length — so cosine similarity reads shape, not raw amplitude, and a loud window and a quiet window with the same internal proportions score as similar. | class | event ↔ event (own class) | rest-of-class ↔ rest-of-class | event ↔ rest of own class | |---|---|---|---| | storm | 0.4488 | 0.3334 | 0.3857 | | class 2 | 0.0286 | 0.0162 | 0.0193 | | calm | 0.0208 | 0.0338 | 0.0006 | *(Null: two independent random samples of the rest of the dataset score 0.003.)* Storm's reversal events do sit well above the null (0.4488 vs 0.003) — but storm's *ordinary*, non-reversal firings are almost exactly as similar to each other (0.3334), and a reversal event looks nearly as close to an ordinary storm event (0.3857) as to another reversal. The kinship is real, but it belongs to the **class**, not to the reversal. In calm, there is not even that much: reversal events are *less* similar to each other (0.0208) than an arbitrary pair of ordinary calm windows (0.0338). Whatever a reversal event of calm is, it is not a recognisable family. ## ④ The full network, the whole window, against the whole dataset Group-level rules were the cheapest hypothesis. Next is the most direct one: a dilated convolutional network — the architecture this project has used to win every comparable grid search since [/class4](/class4) — trained on the raw 8×210 window to separate a reversal window from *any* other window in the dataset, five chronological blocks with an embargo, 233 connected reversal groups (a handful of the original 271 share a window across two detectors and get merged so the same event is not counted twice). Out-of-fold: **AUC 0.6783±0.0282, PR-AUC 0.1588±0.078** against a base rate of 6.8%. At the operating point where the model fires exactly as often as there are true reversal windows: precision = recall = **0.1979**, a **×2.9** lift over chance. This already beats every threshold rule of section ② and every "rejected direction" further down this page — but five out of every six windows it flags are still not a reversal. ## ⑤ Where in the window does the signal live? If a 1680-number window carries this little signal, maybe most of it is dead weight. A grid search over both length and position (231 cells: length 10–210 s in steps of 10, every offset) using fast logistic-regression screening finds a winner at **30 seconds, offset 0** — the first 30 seconds of the window — scoring AUC 0.698, matching the full 210-second window on the same linear model (AUC 0.6536) while carrying 7× fewer numbers. Position barely matters: AUC stays close to 0.698–0.7018 whether the 20–30-second slice is taken from the start or the end of the window. Confirmed with the full network on the same slice: AUC **0.7287**, AP **0.1813** — better than the network on the full window (section ④). Then we tried four separately-trained models, one per quarter of the window (0–30 · 30–70 · 70–140 · 140–210 seconds, boundaries set after this scan), and got a result that looked like it contradicted the scan above: a clean, monotonic decay from the first quarter to the last. | quarter | seconds | OOF AUC | working precision | |---|---|---|---| | a | 0–30 с | 0.7287 | 0.2266 | | b | 30–70 с | 0.7149 | 0.2191 | | c | 70–140 с | 0.6914 | 0.2151 | | d | 140–210 с | 0.6402 | 0.1133 | **This is a confound, not a contradiction, and section ⑥ shows why.** The four-quarter models differ in *two* things at once — length AND distance from the start — while the position scan above holds length fixed. When we later trained one model on all seven 30-second slices of the window as separate examples (section ⑥), AUC across position came back essentially flat: 0.7218 at the start, 0.7215 at the end. The apparent decay belongs to the last quarter's extra length and distance combined, not to a genuine fade of signal toward the end of the window. ## ⑥ One model, all seven slices, at once Instead of four separate models, we cut every window into 7 non-overlapping 30-second slices and trained **one** model to recognise a "reversal slice" on all 7 positions together — 393,841 examples instead of 56,263. A label is inherited from the parent window (all 7 slices of a reversal window count as positive); the fold split and embargo are computed once at the window level and stretched down to slices, not recomputed on the finer grid — recomputing naively on the small unit would have quietly shrunk the real embargo buffer roughly sevenfold, from about 11.7 hours to 1.7. | unit | AUC | AP | |---|---|---| | slices (raw OOF, 393,841 examples) | 0.7213 | 0.1735 | | windows (max of 7 slices, 54,724 windows) | 0.7321 | 0.1847 | Aggregated to the window level, one shared model matches the specialised first-quarter model of section ⑤ (0.7287/0.1813) almost exactly — pooling every position into one dataset costs nothing. At the group level — did *any* of a reversal group's slices cross the threshold — 105 of 233 connected reversal groups are caught (45%). At the operating point matched to the positive count: precision = recall **0.219**, ×3.21 lift. ## ⑦ Splitting by parent class: where the ceiling actually sits Section ③ already hinted that "reversal" means something different in each parent class — storm has some family resemblance, calm has none. The last and most granular test trains three fully independent models (storm, class 2, calm; PCA-quiet has only 1 reversal event and is skipped), each asking "does this look like *my own* class's reversal" against a negative pool built from the *entire* dataset — other classes' windows included. | class | reversal windows (groups) | AUC (slices) | working precision | lift | groups caught | |---|---|---|---|---|---| | storm | 1085 (95) | 0.9577 | 0.3404 | ×17.17 | 43/95 (45%) | | class 2 | 1961 (106) | 0.8177 | 0.1247 | ×3.48 | 30/106 (28%) | | calm | 739 (69) | 0.7215 | 0.0193 | ×1.43 | 5/69 (7%) | This is the single best number the whole study produces: storm's ×17.17 lift, precision 0.3404. It is also, read plainly, one correct signal for every two wrong ones. Class 2 and calm are markedly worse — calm's lift of ×1.43 is barely distinguishable from noise, and its precision, 0.0193, sits right against its 1.4% base rate. Same recipe, same training budget, three classes — and the result spans a factor of six. The AUC numbers alone (0.72–0.96) would suggest something close to usable; it is the AP and the operating-point precision, appropriate for how rare a real reversal event actually is, that show the honest picture. ## ⑧ What we tried and put aside Three more approaches were tried on the group-level representation of section ② before we moved to full-window networks, and all three are left in the code but not on the dashboard tab, because none improved on what is reported above. A **pooled classifier** — one model deciding "is this any of the 271 canonical events" against the *whole* pool of 9,405 groups from all four detectors, with "which class fired" as a legitimate input feature — reaches PR-AUC **0.1542 [0.123, 0.195]** against a null of 0.052. Real signal, three times the null, and still only one correct call in six or seven at any reasonable threshold. A **template match** — the average z-scored profile of all 271 events used as a single direction, and every group scored by how well it projects onto it — reaches a respectable-looking holdout AUC of 0.793, but at the precision-maximising threshold catches only 14% of events at 18% precision. And an **OR-rule built specifically to reach 98% recall** — 13 threshold conditions, each added to cover whatever positives the rule so far had missed — got there: 96.2% recall on the holdout set. It did this by firing on 2721 of 2822 groups (96%). Precision 0.0283 lands exactly on the base rate 0.0283: a lift of 1.0. A rule that technically "catches almost every reversal" the same way an open umbrella catches rain — by covering the whole sky. High recall, stated on its own, proves nothing; every number in this study is reported next to what it costs to get it. ## ⑨ What this is worth Nine methods, one direction of travel. A group-level threshold rule barely clears random. A full network on the whole window reaches ×2.9 lift at 20% precision. Splitting the window by position changes nothing — the same signal is there whether you look at the first 30 seconds or the last. Splitting the *dataset* by parent class changes everything: storm's own detector reaches ×17.17 lift and 34% precision, the best number in the whole study — and calm's reaches essentially nothing. There was a point, partway through this line, where it felt like a working, automated trading signal was close — a detector with a real, reproducible edge, several times better than chance, built on the same architecture that has won every comparable grid search on this dataset. It is not close. Every identification method we tried, across nine different framings of the same question, tops out at a precision too low to act on: even storm, the strongest case by a wide margin, is wrong roughly two times out of three. A rule tuned to be generous with recall is a rule that fires on nearly everything. A model with an excellent AUC still has an unusable AP once the base rate is as low as a genuine reversal's. We are not closing this line. The pieces that survived every control — a real, above-null signal in group-level features, a reproducible network edge against the whole dataset, and a sharp asymmetry between market states that says storm's reversals carry a signature the others do not — are raw material, not a finished answer. What continues from here is a search for a *better way to identify* these events, not a claim that the underlying signal isn't there: on this evidence, it is. ================================================================================ # We Found the Reversal Signal. Machine Learning Could Not Tell It Apart. URL: https://marketflowresear.ch/articles/we-found-the-reversal-signal-machine-learning-could-not-tell-it-apart/ Published: 2026-08-09 · Series: Order-book research · Signals > A market moves in legs: a few percent one way, a turning point, then a few percent the other. This study asks whether the order book carries an event that marks the turn — and whether that event can be separated from the thousands of ordinary events of the same class. On 175 days of BTC the first half works: groups of signals pile up at turning points 3.7× more often than chance, every class shows the same reversal signature, and inside a storm the shape of the flows tells a top from a bottom where price itself says nothing. The second half does not. Every way we tried to learn 'is this a reversal' landed on top of its own null control, and a class retrained with all reversal windows removed still fires on them — harder than on its ordinary events. The signal is real; the discriminator is not. ## ① Legs, groups, and one rule that shapes everything Two markings of the same seconds are laid over each other. The first is **price phase**. A centred 5-minute average smooths the tick noise, a 2.3% ZigZag marks the turning points, and the stretch between two turning points is a **leg**. On our slice: 120 legs (60 up, 60 down), median size 4.2%, median duration 24.5 hours, covering 97% of the time. Note that this marking looks ahead — the smoothing is centred. That is fine for analysis and fatal for trading, and we never let it into a model. The second is **market state**: a window of 8 order-book features × 210 seconds, judged by four detectors trained in an earlier study — storm, class 2, calm and PCA-quiet. And one rule shapes everything that follows: **an event is not a single firing of a detector, it is a group of firings in a row.** Signals arrive in dense clusters inside one move — 50% of storm episodes are single windows, but the rest run a median of 7 minutes and up to 360. Average over firings and every long cluster counts as a dozen separate events; the number you get back is an average over clusters weighted by their length, and it shows an edge that does not exist. The unit is the group, everywhere. A group counts as sitting **at a turning point** if its interval crosses the pivot ±15 minutes. Everything below is reproducible from the research diary that ships with this page — [TRADE08_DIARY.md](TRADE08_DIARY.md): every command in order, the reasoning behind each choice, the traps, and a table of control numbers with tolerances. The full list of every reversal signal we found — 271 events across the four classes, each with its passport — together with the brief for the next study is in [001.md](001.md) next to it. ## ② The signal: storm groups pile up at the turns The null control matters more than the observation here. There are many groups and few turning points, so overlaps happen on their own. So the entire sequence of a class's groups is circularly shifted against price 999 times, and the same count is repeated. Storm groups at leg changes: **95 observed against 26 in the null** (bottom→top 51 vs 13, top→bottom 44 vs 13, p=0 in both). Inside leg bodies the observed counts sit inside the null interval, as they should. PCA-quiet does the opposite — it is essentially absent at turning points (1 against a null of 30). Now read it backwards, which is the only direction that can be traded: a group has just fired — how likely is it that we are at a turn? | storm group | groups | at a leg change | share | |---|---|---|---| | all | 1233 | 95 | 7.7% | | single firing | 553 | 21 | 3.8% | | ≥3 firings | 476 | 66 | 13.9% | | ≥6 firings | 223 | 49 | **22.0%** | Against a base rate of 1.4% of the time being "at a turn", a group of six or more is a 15-fold lift. Keep that number in mind: by the end of the study it is still the only thing that works, and it is a property of the group's **size**, not of what the windows contain. One honest limitation, stated up front. We measured *when* the group arrives relative to the pivot: the median offset is -1.2 minutes, and the pivot comes after the middle of the group in only 45% of cases. Measured from the *end* of the group it is ahead far less often. The event **states** the turn, it does not anticipate it. ## ③ The signature of a reversal — the same in every class Every group is reduced to one average matrix of 8 features × 210 seconds, and the buckets of groups (up leg · down leg · bottom→top · top→bottom · outside legs) are compared. A cell is the deviation of a bucket from the mean **of its own class**, divided by the spread between events of that class, with a Benjamini-Hochberg correction over three 70-second blocks of the window. Why deviation from its own class, not from the market: classes live at different absolute levels — a storm is by definition high flow. Measured against a global mean, every storm map would be red all over and say nothing about reversals. The result is the same in all three classes that have enough reversal events: at a turning point **all flow features are lifted above their usual level and the const walls are pressed down**. What differs is amplitude, and it is largest where you would least expect it — in the quiet classes: | class | events | reversal events | strongest three (deviation, d) | |---|---|---|---| | storm | 1233 | 51 + 44 | resist_plus +0.30 · resist_minus +0.29 · support_plus +0.29 | | class 2 | 3383 | 42 + 64 | resist_plus +0.42 · resist_minus +0.42 · support_minus +0.41 | | calm | 3228 | 31 + 38 | resist_plus +0.56 · support_minus +0.56 · resist_minus +0.56 | A storm at a reversal is only mildly unusual for a storm. A **calm** window at a reversal is very unusual for calm — which is the first hint that "reversal" is not a state of its own but the loud end of whatever state you are already in. There is also something the map does *not* show. The colouring is flat along each row: the difference is one of **level**, not of how the flow is arranged in time. Which is exactly what the next section goes after. ## ④ Shape: the one place the book beats price If level is all there is, then the arrangement inside the 210 seconds carries nothing. So we measured it directly. Each feature of a window gets five descriptors: **level** (mean), **slope** (OLS), **third third minus first**, **curvature**, and **sharpness** (max minus mean). Then: top versus bottom. Two safeguards. The unit here is the **window**, not the group, because there are only a few dozen groups at pivots and this question needs events. And everything runs on **two ZigZag grids** — 2.3% (our legs, 119 pivots) and 1.0% (481 pivots). An effect that shows up on one grid and vanishes on the other is a fit to a particular set of pivots, not a finding. Logistic regression, 5 blocked folds of 12 hours, bootstrap **by pivot** (windows near one extremum are near-copies; bootstrapping over them would give a deceptively narrow interval): | slice | levels only | shape only | price in the same 210 s | |---|---|---|---| | storm, 2.3% grid | 0.623 | **0.691** [0.619, 0.766] | 0.419 | | storm, 1.0% grid | 0.523 | **0.609** [0.565, 0.655] | 0.529 | | all windows, 2.3% | 0.581 | 0.62 | 0.39 | This is the one place in the whole study where the order book beats price. At the extremum price inside 210 seconds does not move — as a predictor it is worse than a coin (0.419) — while the shape of the flows separates a top from a bottom at 0.691, and it holds on the second grid (0.609). The working descriptor is **sharpness**: at a top the burst of `vol_buy` fades across the window, at a bottom `const_support` flares. The obligatory honest note: "price over the last hour" scores 0.9861 on this task — but a pivot *is* the reversal of an hour-long move, so that column is a tautology and stands only as a ceiling, never as a competitor. ## ⑤ Where it stops: three grids and a null control Everything above is description. Turning it into a decision means a classifier, so we built three of them, each with its own full grid (feature sets × model families × hyperparameters: logistic, boosting, forest, kNN, RBF-SVM, dilated Conv1D on the raw 8×210). Three rules keep this honest. **GroupKFold by event** — windows near one extremum are near-copies, so splitting them between train and test hands the model the answer. **The winner is picked among order-book feature sets only** — price sets are controls, and the tautological one wins any grid. **The null permutes labels between events of similar size** — permute freely and the base rate of positives itself shifts, which makes the null's PR-AUC incomparable. | task | rows / events | positives | best | result | null | |---|---|---|---|---|---| | A · top vs bottom | 398 / 79 | 175 | форма (32), логрегресія | AUC **0.7167** [0.627, 0.81] | 0.463 | | B · reversal vs leg body, windows | 4494 / 187 | 398 | рівні (8), ліс | PR-AUC **0.1352** [0.091, 0.21] | 0.129 | | B2 · reversal vs leg body, groups | 1233 / 1233 | 95 | розмір+описи (51), логрегресія | PR-AUC **0.2459** [0.175, 0.34] | 0.08 | Read it in order. Task A — **which side** of a reversal we are on, given that we already know it is one — is solvable, at 0.7167 against a null of 0.463, and the winning feature set is *shape*, not levels. Task B — **is this a reversal at all**, asked of a single window — returns 0.1352 against a null of 0.129: nothing. Task B2, the same question asked of whole groups, returns 0.2459 against 0.08 — a real but modest edge. And then the detail that decides the study: in task B2 the feature set "**size of the group**", three numbers, scores 0.2183 of the winner's 0.2459. Forty-eight descriptors of what the windows actually contain add about 0.03. The reversal is not distinguished by **what the event looks like** but by **how long it is**. ## ⑥ The decisive test: classes retrained without reversals If a reversal event were a distinct subtype of its class, a detector that had never seen one would not fire on it. That is a test, not an opinion, so we ran it: each class was retrained with the production recipe — same architecture from its grid, same 8 epochs, same 2% held out in four contiguous chunks with an embargo, threshold at the base rate — but with **all windows of reversal groups removed from training entirely**, neither positive nor negative. (Putting them in the negative class would place near-identical windows on both sides of the label and simply break the detector.) Quality did not suffer: on the held-out 2% the new storm detector runs at precision 0.9322 / recall 0.9402, class 2 at 0.9042 / 0.9026, calm at 0.9224 / 0.8467 — all within noise of the originals. And on the windows it had never seen, the retrained model fires **more** than on the ordinary events of its own class: storm 99% against 90%, class 2 98% against 91%, calm 91% against 92%. So reversal events are not a separate subtype. They are the **most typical and strongest** representatives of their class — which is why no amount of model capacity separates them, and why the only thing that ever worked was the size of the group. So reversal events are not a separate subtype of their class — and no amount of model capacity will separate them, because there is nothing categorical there to separate. ## ⑦ Why the negatives are contaminated: pullbacks inside a leg There is a structural reason a classifier is being set an unfair question here, and it is worth measuring rather than asserting. A leg is a move from one turning point to the next, but it does not go straight: price keeps falling back against it. To count those, a finer ZigZag is run **inside each leg** and the segments running against the leg's direction are taken. Three thresholds, not one, because the count depends on the threshold more than on anything else: | threshold | pullbacks | per leg (median) | legs with none | size | share of its own leg | duration | typical position in the leg | |---|---|---|---|---|---|---|---| | ≥0.5% | 615 | 4 | 11 of 120 | 0.787% | **15%** | 1.45 h | 41% | | ≥1.0% | 176 | 1 | 45 of 120 | 1.288% | **22%** | 2.8 h | 38% | | ≥1.5% | 56 | 0 | 82 of 120 | 1.753% | **28%** | 4.67 h | 39% | A typical ≥0.5% pullback takes back 15% of its own leg over 1.45 hours, there are 4 of them per leg, and only 11 legs out of 120 have none. At the 1% threshold a pullback is 1.288% deep — which is comparable to the 2.3% that defines a leg in the first place. That is the point. **For the order book, a deep pullback and a reversal are nearly the same event.** When we ask a model to separate "reversal" from "leg body", a large part of the negative class it is told to reject consists of small reversals that our ZigZag threshold happened not to promote. The label is not clean, and no model fixes a label. The same argument runs the other way as well: 37 of the 119 turning points have **no storm near them at all**, and no other class steps in above its own null. Those pivots are simply quieter — the price range ±15 minutes around them is 0.515% against 0.869% where a storm is present. So the positive class is incomplete too. ## ⑧ What this is worth **Found.** Groups of storm signals concentrate at turning points 3.7× above chance and survive a 999-shift null. The reversal signature is identical across classes — all flow features up, walls down — and strongest in the quiet ones. Inside a storm the *shape* of the flows separates a top from a bottom at AUC 0.691 on two independent ZigZag grids, in a window where price itself is worse than a coin flip. **Not found.** Any way to decide, from the content of a window, that this event is a reversal. Window level: 0.1352 against a null of 0.129. Group level: 0.2459 against 0.08, and 0.2183 of that comes from three numbers describing the group's size. Classes retrained without reversal windows recognise them better than their own ordinary events. And the event arrives **at** the turn, not before it. We are stating this as a negative result on purpose, because the shape of the negative is informative: the failure is not "there is no signal in the order book" — the signal reproduces against every control we could build. The failure is that a reversal is not a different *kind* of event, it is the loud end of an ordinary one, and a classifier asked to separate degrees of loudness inside a continuum has nothing categorical to hold on to. Which is also why we think this line is worth continuing rather than closing. The pieces that survived every control — group size, the shape asymmetry inside a storm, the identical signature across classes — are the raw material of a decision rule, not of a classifier. Our working expectation is that further study of these reversal signals will make an effective trading bot possible: what is missing is not the signal but a way to separate it from the rest of its class. Everything here ships with a research diary written as an executable recipe: the commands in order, the reasoning behind every choice, the six traps we actually fell into — including a null control that quietly moved its own base rate, and a claim about groups that we spent a day testing on windows — and a table of control numbers with tolerances, so you can tell whether your own run reproduced ours — [TRADE08_DIARY.md](TRADE08_DIARY.md), right next to this page. Take your own data and check. ================================================================================ # Sixteen Networks, One Working Answer — and the Price Benchmark That Nearly Killed It URL: https://marketflowresear.ch/articles/sixteen-networks-one-working-answer/ Published: 2026-08-08 · Series: Order-book research · Nets > We trained sixteen one-class autoencoders on Bitcoin order-book windows: four market states, and inside each state one network per phase of the price move. Each network saw only its own kind of window and nothing else — no negative examples at all. One thing out of sixteen works: inside a storm you can tell a bottom reversal from a top one. On half the data that looked like AUC 0.6264; measured properly on all 800 events it is 0.5928. Then a one-line price benchmark scored 0.8548 on the same question. This article is about what survives that, and where it survives. ## ① Sixteen networks that never saw a counter-example Two markings of the same seconds go into this study, and neither is produced here. The **market state** comes from four detectors trained in an earlier study — storm, PCA-quiet, class 2 and calm — applied to windows of 8 order-book features × 210 seconds, out-of-fold, so every window is judged by a model that never saw it. The **phase of the move** comes from a ZigZag study: 1% ZigZag marks local extrema, a zone is the stretch while price stays within 0.5% of the extremum, and that yields four phases — bottom reversal, top reversal, down leg, up leg. Then for each of the four states we train four networks, one per phase. The network for "storm in a bottom reversal" sees only storm events that fell inside a bottom reversal — nothing else. No windows from other phases, no windows from other states, and above all **no negative examples**. This is deliberate: the question "how does a storm at a reversal differ from a storm mid-leg" is not two labels of one phenomenon, it is two kinds of window. So the tool is a one-class Conv1D **autoencoder**, and its answer to any window is the reconstruction error. Three decisions about the split, each with its own reason. **We split days, not events.** Windows lie on a continuous 210-second grid; neighbours are nearly identical — the same hour of market, shifted by three minutes. A random split trains on the window at 14:00 and "tests" on the window at 14:03. Of the 129 days with storm events, 64 are declared validation. The price of honesty: halves are unequal in events (191 train against 225 validation for top reversals), because days differ in how busy they are. **The split is shared by all four networks.** Otherwise one network's validation days would be another's training days, and the joint question "whose error is smaller" would be a contest in memorisation. **Early stopping may not look at the validation half.** Where to stop is a parameter, so another 10% is carved out of the *training* half for it. And the errors of four networks cannot be compared raw. A network trained on 945 examples has lower error on *any* window than one trained on 191, simply because it saw more. So each error is first converted to a **rank within its own network's distribution**, and only then compared. Beside every number stands its null control: the same four networks on **shuffled** phase labels, same split, same validation. It answers "how much accuracy accrues merely from four networks having been trained on four different chunks of history" — and the answer is: quite a lot. In storm, the null control reaches an accuracy of 0.2275 where chance is 0.25. ## ② One thing works, and only in one class On the validation half, three questions are asked of the same four errors: whose phase is this (four-way, chance 0.25), bottom reversal versus top, and reversal zone versus the body of a leg. • **storm** — accuracy 0.2943 against a null of 0.2275; **direction 0.6264 against a null of 0.4241**; zone-versus-leg 0.5221 against 0.4772; • **PCA-quiet** — 0.2612 / 0.2555, direction 0.5751 / 0.5425: inside its own noise; • **class 2** — the only other hint, and a weak one: zone versus leg 0.5471 against 0.5052; • **calm** — 0.2458 / 0.2538, direction 0.5025 / 0.5206. Every metric at or below its own null. Calm events look the same in all four phases. So: one working cell out of sixteen networks and twelve metrics. Direction — the thing this project has failed to read for months — is readable inside a storm, and nowhere else. That is the point at which most write-ups stop. It is also the point at which the number is least trustworthy: it is measured on half the data, has no confidence interval, no operating threshold, and no answer to "how many times out of ten". ## ③ Making the number usable — and watching it shrink Four changes, in order. **Double cross-fitting.** In the first pass, networks learned on the first half of days and were measured on the second, so half the events had no score at all. Now a **mirror** pair of networks is trained on the validation half and used to score the training half. Every event gets an answer from a model that never saw it, and the sample doubles from 384 to 800 zone events (384 bottoms, 416 tops, 298 distinct extrema). The first honest consequence: **0.6264 becomes 0.5928** [0.5329; 0.6533]. Half-data estimates run optimistic; that difference is ordinary variance on a few hundred events, and it is exactly why a single number without an interval is not a result. **An ensemble, assembled without fitting.** Beside the networks we put the same 16 descriptors (8 levels + 8 in-window slopes) used in the phase study, and average the two answers' ranks — no weights, because any weight tuned on these 800 events would be fitting. Descriptors alone give 0.5698; the ensemble 0.6024 [0.5423; 0.6633]. The gain over networks alone is 0.01 — comfortably inside the noise. Adding in-window price to the ensemble makes it *worse* (0.569). **Bootstrap over zones, not windows.** A zone holds 2.68 windows on average and they are nearly identical. Resampling windows pretends they are independent and returns an interval 1.59× narrower than the honest one ([0.564; 0.6399] against [0.5423; 0.6633]). The unit of resampling has to be the unit of independence. **A working threshold.** The answer is turned into a rank within its fold, and a signal is given only on the extreme q% at each end; everything else is "don't know". At q=0.15 — that is, answering on 30% of events — 67.4% are correct (68% of "bottom" calls, 67% of "top" calls), against 49.8% for the null control at the same coverage and 47.1% for in-window price. Tightening further does not help: at q=0.05 accuracy falls back to 61.3%, because only dozens of events remain in the tails. **Month by month** the signal is not constant: 0.6516 in 2026-06, but 0.507 in 2026-03 — nothing at all in one month out of five. That is the ceiling on how much this deserves to be trusted. ## ④ The benchmark that nearly kills it — and the one place it does not Price inside the same 210-second window scores 0.4722 on "top or bottom" — nothing, exactly as expected: at an extremum price does not move for three and a half minutes. But there is a second price benchmark, and it is not polite. Take the percentile of the current price among the observations of the last 24 hours — one line of code, information the networks never see because it lies outside their window. It scores **0.8548** [0.8038; 0.8994]. The honest reading is not "the order book is useless". It is that our label is nearly a function of that benchmark: a top and a bottom are *defined* by a ZigZag over price, so where price sits in its own recent range is an almost tautological predictor. Hiding it would be dishonest; surrendering to it would be sloppy. The right move is to stratify by it and ask what is left for the book **where price is silent**. Split the events into thirds by how far the percentile sits from the middle of the day: • **the third where price is mid-range** (|percentile − 0.5| ≈ 0.234, 267 events): price scores 0.5251 — i.e. nothing — and the order book 0.5781; • **the middle third** (0.469): price 0.8405, book 0.5391; • **the third where price is at the edge of its daily range** (0.498): price 0.974, book 0.6916. That is the whole practical truth of this line. When price has already committed to an edge of its range, it answers the question itself and the book adds nothing worth having. When price sits in the middle and says nothing, the book is the only thing that speaks — modestly, but it is the only one speaking. One more warning that follows directly: a naive blend of the two, averaging their ranks, scores 0.8134 — **worse** than price alone at 0.8548. The book is a regime-conditional signal, not an ingredient to stir in. ## ⑤ A hypothesis that failed: networks on subclasses An earlier study showed that in the quiet classes, events inside reversal zones are *stronger* — the top tercile of intensity turns up there more often. That suggests an obvious improvement: if phases differ mainly by the strength of the event, then a network trained on events of a single strength should separate them better, because it does not have to spend capacity on the strong-versus-weak difference that has nothing to do with phase. So: twelve networks per class instead of four, one per phase × intensity tercile. One design decision decided everything here. The tercile is cut **across the whole class**, not inside the phase. Cutting inside the phase would (a) put 34/33/33 in every column by construction, leaving nothing to compare, and (b) — fatally — make the tercile depend on the phase label: to choose which trio of networks an event belongs to you would already have to know the answer. That is a leak into the problem statement itself, and no metric would reveal it afterwards. Everything is compared on the *same* validation events: subclass networks, the base networks from step ① (not retrained — literally the same models), and a null control of subclass networks on shuffled phase labels. The headline number is the **paired** difference with a bootstrap over zones, because both estimates come from one sample. Result: **separation did not grow.** In storm the paired differences are -0.056 [-0.1771; 0.0502] for the top tercile, +0.077 [-0.0406; 0.19] for the middle and -0.013 [-0.2113; 0.1584] for the weakest. Not one interval clears zero. In the quiet classes the split simply runs out of data: PCA-quiet lost 5 of its 12 networks to the 40-example minimum, because its zone events are rare to begin with and thirds cut them by three again. There is a side observation worth more than the hypothesis. Look at the base networks' column: the same four models read direction differently in different terciles — 0.6433 on the strongest events, 0.6773 on ordinary ones, 0.555 on the weakest. The direction signal does not live in the most violent storms, as intuition suggests. It lives in the middling ones, and disappears in the weak. ## ⑥ What this adds up to Four things survive. **One.** Out of sixteen one-class networks, one cell reads: direction of a reversal inside a storm. Measured on all 800 events with every event scored by a model that never saw it, it is 0.5928 [0.5329; 0.6533] against a null of 0.4774, ensemble 0.6024, and at a working threshold 67% correct on 30% of events. It is real and it is small. **Two.** "Storm is the special class" is *not* established. In calm, the same 16 descriptors score 0.5882 [0.5492; 0.6288] against a null of 0.5222 on 4,175 events — a narrower interval than storm's, because there are five times more events. What is special about storm is that *networks* work there; the descriptors work in calm just as well. **Three.** A one-line price benchmark beats all of it at 0.8548, for a reason worth naming out loud: the label is built by a ZigZag over price. The order book earns its place only in the regime where that benchmark is silent — price mid-range — and there it is 0.5781 against price's 0.5251. Blending the two naively makes things worse. **Four.** The subclass hypothesis failed cleanly, which is its own kind of result: cutting events by strength did not sharpen anything, and the direction signal turns out to live in the *middling* storms rather than the strongest. All of it ships with a research diary written as an executable recipe: commands in order, the reasoning behind each choice, the traps we actually fell into — including a 97%-accuracy result that was pure memorisation, and a tercile cut that would have leaked the answer into the question — and a table of control numbers with tolerances so you can tell whether your own run reproduced ours. Take your own data and check. ================================================================================ # Does the Phase of a Move Change What the Order Book Looks Like? URL: https://marketflowresear.ch/articles/does-the-phase-of-a-move-change-what-the-order-book-looks-like/ Published: 2026-08-07 · Series: Order-book research · States > We have four detectors of market state and a map of where price is in its move — reversal zones and the legs between them. Laying one over the other answers a question that sounds simple and is not: does the phase of a move change what a market state looks like? On 171 days of BTC the answer splits. The count of events barely moves — each class fires roughly in proportion to how long the phase lasts. What moves is their strength, and only for the quiet classes. And in one narrow place the order book finally beats price: telling a top from a bottom inside a storm. ## ① Two markings of the same time Everything here compares two labellings of the very same seconds. The first is the **market state**: a window of 8 order-book features × 210 seconds, classified by four detectors trained in another study — storm, PCA-quiet, class 2 and calm. Answers are taken out-of-fold: every window is judged by a model that never saw it. The second is the **phase of the move**, from our ZigZag study: a 1.0% ZigZag marks local extrema, and a zone is the stretch during which price stays inside a 0.5% band around the extremum. That gives exactly four phases: bottom reversal, top reversal, down leg, up leg. A window belongs to the phase its **middle** falls into. The scale everything must be read against is time. Bottom reversals take 6.9% of the dataset (367 stretches, median 25 min), top reversals 8.2%, the down leg 41.8% and the up leg 42.7%. Reversal zones together are 15.0% of all time; the legs are 84.5%. A reversal lasts about half an hour, a leg about two. One detail that costs a rerun if you miss it: the four classes are **not** mutually exclusive. They are four separate detectors, and out of 44,698 windows inside phases, 6,178 have two classes active at once and 391 have three. ## ② How often each state fires in each phase The simplest question first: does a class fire more often in a reversal than in the body of a move? Each model is compared only against itself — their bases differ by an order of magnitude (9.3% of the time for storm, 61.4% for calm), so the table shows lift, not raw rates. Two of the four react, and they react in opposite directions. **Storm** fires ×1.325 more often in a reversal zone than in the body of a leg; **PCA-quiet** ×0.7, i.e. less often. Class 2 (×0.895) and calm (×1.008) sit entirely inside the null control. That null control matters more than the numbers. Phases are long and strongly autocorrelated, so any lift looks impressive until you shift the model's answers in time relative to the labelling — which destroys the link with the phase but keeps the autocorrelation of the answer itself. Over 999 such shifts the storm contrast lands at p=0.014 and PCA-quiet at p=0.01; everything else fails. Direction is not readable at this level at all. Bottom reversal against top reversal is ×1.013 for storm against a null of ×1.041 — nothing, and the same for every other class. The only asymmetry lives in the legs: PCA-quiet fires ×0.65 down-versus-up (p=0.002), meaning rises are quieter than falls. ## ③ The features themselves, phase by phase So far we compared what the models **said**. Now we compare what they **saw**: the 8 × 210 matrix in exactly the form it is fed in. Each cell is how far a feature's level in this phase deviates from the mean of its own class, in class SD units — that makes all eight features and all four classes comparable despite different units and very different bases. The general picture is the same in every class: inside reversal zones all six flow features are lifted above their usual level (+0.24 for support_plus at a bottom), and in the up leg they are pushed down (-0.11). It holds **inside each class separately**, so it is not a composition effect. And here is where direction hides. The top-versus-bottom difference is delivered not by storm but by **PCA-quiet**: vol_sell is +0.33 at a top reversal against -0.30 at a bottom — a spread of 0.63 d, the largest in the whole map. In storm that same place is nearly empty: there all eight features are already at their maximum, and the phase adds no information. Shape works in exactly one class. Inside storm windows the slope of vol_buy is -0.19 at a top: buying fades across the 210 seconds. In the quiet classes the slopes are empty — in a still window there is nothing to tilt. ## ④ Inside each class: the 1680 numbers, and the honest benchmark Per-class, per-second now. Each class answers differently, and that is the point: • **storm** separates tops from bottoms only by its walls: const_support +0.20, const_resist +0.19, while the flows go negative (-0.30 for support_plus) — the book is busier at bottoms; • **class 2** has all six flows lower at tops (-0.17…-0.14); • **calm** shows vol_sell +0.27 together with const_resist +0.23: in a quiet window at a top there is simultaneously a thicker sellers' wall and more selling; • **PCA-quiet** pushes that same signature to vol_sell +0.67, the largest effect in the entire study, though on only 432 zone windows. Now the number that matters most, and the benchmark that keeps us honest. On "top or bottom", five blocked folds inside each class: the order book scores 0.530 to 0.587, while **price** inside the very same window scores 0.419 for PCA-quiet, 0.459 for class 2, 0.484 for calm and 0.498 for storm — nothing at all, in all four. It is modest, but it is not a shadow of price, and it replicates across four independent subsamples. In an extremum price does not move for 210 seconds, so it has nothing to say; the book still does. One more thing worth stating plainly: the full 1680 numbers lose to 16 summary descriptors everywhere except class 2, where there are most windows. A network input that wide needs more than a few hundred examples per cell. ## ⑤ The strongest events are the least characteristic Next we cut every (class × phase) group into three parts inside itself: the 34% most distinct events, the 33% typical ones, and the 33% weakest. Two orderings, because "most distinct" reads two ways — by **intensity** (mean z of the eight levels) and by **atypicality** (Mahalanobis distance from the group's own centre). The goal was to find the events that look the same everywhere, i.e. that say the least about their class and phase. The answer came out backwards from the expectation. Recognising the class of an event works at 0.686 on the top third, 0.821 on the middle, and 0.847 on the weakest third (all events together 0.839, chance 0.25). By atypicality the order is the same: 0.779 → 0.876. So the look-alike events are not the middle third — they are the **top** one. At peak intensity all four classes look the same: a strong event is a strong event, and that is exactly when it tells you least about which class produced it. There is also no shared zone for all sixteen groups at all. The intersection of the middle-tercile boxes is non-empty in only 0 of 8 features, and with a softened 10–90 box, 2. The classes simply sit in different places of the level space. What does work as a definition is a model's own doubt: events that neither the group model nor the class model can attribute — 6,908 of them (20%), on which the class is guessed at only 0.534 instead of 0.839. They are spread very unevenly: storm stays recognisable almost always, while the boundary between the quiet classes is genuinely blurred. ## ⑥ The count barely moves — the strength does Finally, the plain bookkeeping: how many events of a class fall into each phase, and how strong they are. The terciles here are cut **across the whole class**, not inside the phase — otherwise every column would read 34/33/33 by construction and there would be nothing to compare. The count of events follows time almost exactly: 5–10% of each class's events land in reversal zones, which take 15% of the dataset. Nothing interesting there. The strength is a different story: • **storm** is the one class the phase does not touch: 32–36% top-tercile share in every one of the four phases, χ² p=0.15. A storm at a reversal is exactly as strong as a storm mid-leg; • **class 2** gives 48% top tercile at a bottom reversal against 31% on the up leg (p=5e-33); • **calm** 44% at a top reversal against 29% on the up leg (p=2e-86); • **PCA-quiet** 42% at a top against 28% at a bottom (p=3e-03). In other words: in reversal zones the quiet classes fire with their strongest events, and on the way up with their weakest. The up leg has the largest share of the weakest tercile everywhere. Read from the other side — with the phase's windows as the denominator — the same fact looks like this: storm's lift in a reversal is spread evenly across all three subclasses (bottom reversal ×1.272 overall, ×1.324 for its top tercile), so there is simply *more* storm there, not stronger storm. Calm at a top reversal is ×1.044 overall but ×1.362 for its top tercile — the class does not appear more often, it appears stronger. By **atypicality** all of this vanishes (p from 0.00 to 0.59): the phase shifts the strength of an event, but does not make it strange for its own class. ## ⑦ What this adds up to Three things survive from all of the above. **One.** The phase of a move does not decide *whether* a state appears — the counts follow the clock. It decides *how strong* the state is when it appears, and only for the quiet classes. Storm is indifferent to the phase. **Two.** Direction — the thing this project has failed to read for months — is finally readable in one narrow place: telling a top from a bottom **inside a storm**, at 0.587 against price's 0.498 in the same window. The mechanism is visible in the features: at a top both walls are thicker and buying fades across the window; at a bottom the book is busier and buying builds. **Three.** The strongest events are the least informative about their class. That is worth remembering next time a filter is built on "take the strongest signals" — on this data that is precisely the subset where the classes stop being distinguishable. Everything here ships with a research diary that is an executable recipe: the commands in order, the reasoning behind each choice, the traps we actually fell into (including two that cost full reruns), and a table of control numbers with tolerances so you can tell whether your own run reproduced ours. Take your own data and check. ================================================================================ # Eight Ways to Compress 210 Seconds: the Autoencoder That Lost to PCA URL: https://marketflowresear.ch/articles/the-autoencoder-that-lost-to-pca/ Published: 2026-08-06 · Series: Order-book research · Autoencoder > We cut 170 days of per-second Bitcoin order-book data into 50,143 back-to-back windows and pushed them through eight different compressions — PCA, a convolutional autoencoder, and six variants of both — to see whether a network finds market structure a linear method misses. It does not. Its raw stability is the best in the table and most of that stability survives when the data is shuffled into noise, which means it was never structure at all. ## ① A dirty tape, cut end to end This study asks one question: when the whole tape is cut into windows — not just the interesting moments — does a neural network find structure that a linear method cannot? Before any model, the data had to be made honest. The raw BTC series is **12,165,288 rows**, and 192,496 of them are duplicate timestamps; left in place they let neighbouring windows share seconds, which quietly leaks training data into validation. After de-duplication 11,972,792 rows remain. Then the uncomfortable number: laid on a continuous per-second grid the series should hold 14,691,826 seconds, and **18.507% of them are simply not there**. Gaps are filled by interpolation, but a window is only used if at least 95% of its seconds are real. That leaves **50,143 windows** of 210 seconds, cut back to back with no overlap, averaging 99.46% real seconds. Every feature is divided by its own 14-day norm. The split is blocked, not random: the timeline is cut into 2-hour blocks, 5,061 windows go to validation, and **2,120 windows within 30 minutes of a validation block are deleted from training** — because adjacent windows are correlated and a random split would let the model read the answer from its neighbour. ## ② Nine configurations, and how little they mattered The autoencoder is a 1-D convolutional network: eight features as eight channels, convolution along time only, trained to reconstruct the window it was given. Nine configurations were trained — three bottleneck widths (16, 32, 64), three depths, three noise levels, three learning rates. The winner is bottleneck 64, depth 3, input noise 0.2, learning rate 0.002, with validation loss **0.10547**. The loser scores 0.12453. That is the whole story of the grid: **the spread across every architecture we tried is 0.019**, and the only parameter that moves the number at all is the bottleneck width — which is to say, capacity, not cleverness. A wider bottleneck reconstructs better. It does not, as we will see, produce better classes. Those two things are not the same question, and conflating them is the most common way to fool yourself with an autoencoder. ## ③ Where the training actually stopped The production model was then trained properly: **308,808 weights**, 72 epochs, and the weights kept are those of epoch **64** — the point where validation loss stopped improving while training loss kept falling. Final validation loss 0.10476. This is bookkeeping, not a result, and it is here for one reason: every number in the rest of this article comes from that checkpoint, on windows the network never saw, with the embargo enforced. If the stopping point were chosen on the same data the classes are measured on, none of what follows would mean anything. ## ④ What the network reproduces — and what it gives up on Reconstruction loss in a standardised scale is unreadable, so it was converted into something you can argue with: by what factor does the reconstruction miss the true value, feature by feature, on validation windows. The two resting walls come back at **×1.35** — nearly exact. The four flows miss by ×5.08 to ×6.17. Executed volume is hopeless: ×12.74 and ×13.60. That single chart explains why a shared latent space is a trap. The walls are smooth and large, the flows are spiky and small; a reconstruction loss rewards getting the walls right, so **the walls dominate the compressed representation** and the flows — which the neighbouring study shows to be the thing that actually distinguishes market states — get compressed away. Training one model per half of the book (walls: validation 0.00900; flows: 0.12650) is not a refinement here, it is a correction of that bias. ## ⑤ Eight compressions of the same windows, one rule The same 50,143 windows were then pushed through eight different compressions — PCA, the autoencoder on all eight features, the autoencoder on each half of the book, two coarse-grained variants, and the recipe borrowed from the neighbouring [market-states study](/articles/two-poles-of-market-activity-found-on-six-coins/) — and clustered identically downstream. Every one of them is judged by the same two things. **Stability**: rerun the pipeline on subsamples and measure how much two independent runs agree. **The null control**: run the identical pipeline on data whose cells have been shuffled between windows, so that all structure is destroyed and only the marginal distributions survive. The gap between those two is the only quantity that means anything. And a third check, the size rule: a partition where one class swallows more than 30% of the windows, or where a class holds less than 8%, is not a partition of the market — it is a rounding error with labels. **2 of the 8 spaces satisfy it** (10-second buckets, per-feature scale, the /states recipe on every window); the other 6 do not. PCA is the sharpest illustration. Its gap looks magnificent — 0.472 stability against a null control of exactly 0.000 — and it is worthless, because **91.5% of all windows land in a single class**. A stable answer and a useful answer are different things. ## ⑥ The null control eats the network's advantage Read the red bars in the chart above and the case against the autoencoder is finished. On all eight features the network reaches stability 0.709 — the kind of number that gets published. Its null control reaches **0.599**. Almost all of that stability is manufactured: the same network, given windows whose contents were shuffled between each other, still assembles a partition it can reproduce. The honest gap is +0.110. It is not an isolated case. Across the five spaces built from a trained encoder (autoencoder on all 8 features, autoencoder on the 2 walls, autoencoder on the 6 flows, the /states recipe on a 15k subsample, the /states recipe on every window) the null control runs **0.339 to 0.599** — not one of them is anywhere near zero. Of the three spaces built without a network, two sit at exactly 0.000 and the third at 0.359. Put a deep encoder in front of UMAP and HDBSCAN and you get beautiful, reproducible, entirely fictional clusters; the only thing standing between that and a published "market regime" is a control most people never run. One caveat in our own numbers, in the same spirit. Stability here is measured with the space held fixed — the encoder is trained once and only the clustering is rebuilt on subsamples. A full rebuild, network included, would score lower, so **every stability figure in this article is an upper bound**. That does not rescue the network: its null control is measured exactly the same way, and it is the distance between the two that the verdict rests on. This is the third time this project has reached the same conclusion from a different direction — [event classes](/articles/event-classes-found-without-a-teacher/) and [window classes](/articles/no-classes-in-the-order-book-only-one-state/) both ran into it — and it is the single most portable lesson here: **if your clustering has no null control, you do not have a result.** ## ⑦ Where classes do survive Two spaces come through with both a real gap and a legal partition. **10-second buckets, per-feature scale** — the window coarsened from 210 per-second values to 10-second buckets, each feature scaled on its own — gives stability 0.710 against a null control of 0.359, a gap of **+0.351**, with the largest class at 28.2% and the smallest at 11.4%. **the /states recipe on every window** passes the size rule too, but its gap is only +0.085 — on this continuous, per-second dataset the recipe that works cleanly on the sliding set is much weaker. The pattern across the eight is consistent: on raw per-second windows the splits either degenerate into one giant class or ride on a null control that is nearly as stable as the data. Structure appears once the window is **coarsened** — averaged into 10-second buckets, which is roughly the timescale at which order-book flow is actually organised. The fine per-second texture is not carrying the classes; it is carrying noise that the network is happy to memorise. ## ⑧ What we take from this The network was given every advantage — its own architecture search, a blocked split with an embargo, 308,808 weights, and the same downstream clustering as everything else — and it did not earn its place. On raw stability it wins; on stability minus what the same pipeline invents from shuffled data, it loses to a linear rotation of axes that runs in a fraction of the time. Three things are worth carrying out of here even if you never touch an order book. Reconstruction quality is not class quality — a wider bottleneck reconstructed better and clustered no better. A shared latent space belongs to whichever feature is largest and smoothest, so the interesting, spiky part of your data gets compressed out unless you separate it by hand. And the null control is not optional: it is the difference between a finding and a picture. The companion studies: **[Two poles of market activity](/articles/two-poles-of-market-activity-found-on-six-coins/)**, which is the same question asked on non-overlapping sliding windows across six coins and gets a clean answer, and **[There are no classes in the order book](/articles/no-classes-in-the-order-book-only-one-state/)**, which tightens the input constraint until only the window's own numbers remain. ================================================================================ # Two Poles of Market Activity, Found Without a Teacher on Six Coins URL: https://marketflowresear.ch/articles/two-poles-of-market-activity-found-on-six-coins/ Published: 2026-08-06 · Series: Order-book research · Market states > We cut 122–141 days of per-second order-book data on 6 coins into 164,342 windows of 210 seconds, showed a clustering pipeline nothing but the eight order-book features, and asked whether the market falls into natural states. It does — two poles of flow activity with a wide grey zone between them — and the same pipeline run on shuffled data produces nothing, which is what makes the answer worth reporting. The walls turn out to be irrelevant to the split, and the autoencoder we brought in to beat PCA lost to it. ## ① One question, and a deliberately blind input Does the market fall apart into natural states? Not into the states we invented — into whatever the data itself insists on, if we take away every crutch. So the input was made deliberately blind. One observation is a window of **210 seconds** holding eight order-book features — the two resting walls, the four flows building and draining them, and the two executed volumes — each divided by its own **28-day norm** so that a quiet coin and a loud coin are on the same scale. Price does not enter. Time of day does not enter. Neither does duration, or what happened in the neighbouring window. Windows are cut every 300 seconds, so no two of them share a single second, and the first 28 days of every coin are thrown away because the norm is not warm yet. That leaves **164,342 windows across 6 coins** and 122–141 days each. Everything below is what came back. The chart already contains the least comfortable part of the answer. Two states do appear on almost every coin — an active pole and a quiet one — but they are the *edges*. On Bitcoin the active pole is 0.7% of all windows and the quiet one 8.3%, while 61% of the time sits in between, in a continuum that refuses to be a class. This is not a taxonomy of ten market regimes. It is one scale with two ends. ## ② Clustering always returns something — so we ran it on nothing Hand a clustering algorithm pure noise and it will hand you back tidy clusters. That is not a risk to be mentioned in a footnote; it is the default outcome, and it is why most "market regimes" you read about are decoration. So every number here is measured twice. Once on the data. Once on a **null control**: the same pipeline, the same code, the same parameters, run on a copy in which every cell (feature, second) has been shuffled between windows. Distributions survive, structure is destroyed. Whatever the pipeline reports there is what it manufactures out of nothing. Stability itself is measured by rerunning the whole thing on 80% subsamples and asking how much two independent runs agree (adjusted Rand index, 1.0 = identical partitions, 0 = chance). PCA scores **0.561–0.605** across the 6 coins. Its null control scores **0.000–0.008** — that is, essentially zero. The gap is **+0.553–0.605**, and the spread between six independent coins is in the second decimal place. On 5 of 6 coins the answer is the same k = 2. That is the result: the split is not an artefact of the method, because the method given structureless data produces nothing at all. ## ③ The autoencoder was not needed The obvious objection is that PCA is a linear rotation of axes and the market is not linear. So the identical pipeline was run with a convolutional autoencoder in place of PCA — eight features as eight channels, convolution along time only, trained on each coin, everything downstream unchanged. On raw stability it ties: **0.541–0.583** against PCA's 0.561–0.605. On the number that decides the question, it does not. Its **null control jumps to -0.005–0.339** — on some coins the network assembles a "stable" partition out of data whose structure has been destroyed, and the honest gap falls to +0.244. A method that finds order in shuffled noise is not one you want deciding what a market state is. And it costs: 61–99 seconds per coin for PCA against 1,775–2,344 for the network — roughly **24× more compute for a worse guarantee**. We keep reporting this comparison because the reflex to reach for a network is strong and, in this line of work, usually wrong. A companion study took the same network apart in detail — [eight ways to compress 210 seconds](/articles/the-autoencoder-that-lost-to-pca/) — and found the same thing from the inside: its stability is real, and so is the stability it produces from shuffled noise. ## ④ What actually separates the two poles Now the interesting part. The two poles are not "high price movement" and "low price movement" — price was never shown to the model. So what is different about them? Feature by feature, with the band covering the 5th to 95th percentile of each class, the answer on Bitcoin splits the eight features cleanly in two. **6 of them separate the poles completely** — their bands do not overlap anywhere — and every one of those 6 measures something *moving*: liquidity arriving into and draining out of the two walls (×23 to ×48) and executed volume (×93 and ×107). The two features that do **not** separate are exactly the two static ones. `const_resist` differs by ×1.21 between the poles and `const_support` by ×1.24 — that is, not at all — and their bands sit on top of each other. **The thickness of the wall does not define the state of the market.** A quiet market and an active one carry the same resting liquidity; what changes by two orders of magnitude is how much of it moves. Read plainly: a market state is *the movement of orders around the walls*, not the size of the walls. That is the same asymmetry this project keeps arriving at from other directions — resting liquidity is scenery, moving liquidity is the signal. ## ⑤ Six coins, one answer — and one coin that argues A finding on one coin is an anecdote. The same pipeline was therefore run independently on all 6, with no shared parameters beyond the recipe. Two things repeat everywhere. The flows differ between the poles by **an order of magnitude or more on 5 of 6 coins** (BTC, SOL, BNB, XRP, DOGE) — ×12 at the weakest, ×50 at the strongest. And the walls **barely move**: across all 6 coins the active-pole-to-quiet-pole ratio of the two resting walls stays between ×0.40 and ×1.24 — at most a quarter thicker, on two coins actually thinner, never anything like the order of magnitude the flows show. Complete separation — bands that never overlap — is stricter and is reached on 4 of 6 coins (BTC, SOL, BNB, DOGE). On the other two the poles are still ordered the same way, just not disjoint. That distinction matters for anyone who wants to use this: the *shape* of the answer is universal, the *sharpness* of it is not. The clearest exception is worth stating plainly rather than hiding. On ETH the clustering split differently: k = 3 instead of 2, with the "active" class swallowing 80% of all windows and the quiet pole reduced to a sliver. When one class covers most of the data, the contrast between poles collapses — which is exactly what its row in the chart shows. ETH did not contradict the finding; its partition simply is not the same partition, and averaging it into a single headline number would have hidden that. ## ⑥ The strongest single piece of evidence The clearest argument that the poles are real is not a metric at all. It is that two methods with nothing in common find the same ones. Take only the windows where both engines — the linear rotation and the convolutional network — confidently assigned an extreme state. On 5 of 6 coins they agree on **99.9% or more** of those windows; on ETH, the coin whose partition came out differently in the first place, agreement is 73%. Two engines that share no assumptions, no loss function and no geometry are pointing at the same windows and calling them the same thing. That is harder to fake than any single stability score. ## ⑦ What this is not Four limits, because a result without its boundaries is advertising. **It is not a full partition of the market.** The named classes cover roughly 40–50% of the time. The rest — 61% on Bitcoin — is a continuum with no dense clumps in it. The honest statement is "two edges and a long middle", not "the market has N states". **It is a split by level, not by structure.** What differs between the poles is how much flow there is, not who is winning: the internal balance of the eight features — which side of the book dominates — is nearly the same in both states. Order-book *shape* is not what the split is made of. **It says nothing about direction.** Nothing here predicts up or down; the whole project's experience is that the order book forecasts size, not sign, and this study was not built to challenge that. **A stable split is not a tradeable one.** These are states, not signals. Turning one into an entry rule means paying 0.30% per round trip, and that test belongs to a different study — one where the detector runs forward on windows it has never seen. ## ⑧ What we take from this Three things survive from this study. The market does have two ends of an activity scale, they are found without a teacher, they are found on 6 coins independently, and the pipeline that finds them produces nothing when the structure is removed. The distinguishing quantity is the *flow* of limit orders, not the resting size of the walls. And the fashionable engine lost to the boring one: an autoencoder matched PCA on stability, manufactured order out of shuffled noise where PCA did not, and cost ~24× more to run. Two neighbouring studies read well next to this one. **[Event classes found without a teacher](/articles/event-classes-found-without-a-teacher/)** asks the same question on event windows rather than on the whole tape and shows exactly how much "structure" a null control can eat. **[There are no classes in the order book](/articles/no-classes-in-the-order-book-only-one-state/)** tightens the constraint until a window may be judged only by its own 1,680 numbers — and finds a continuum with one sharp state in it, which is the same shape of answer this study arrived at from the other side. And **[eight ways to compress 210 seconds](/articles/the-autoencoder-that-lost-to-pca/)** is the autoencoder verdict above, taken apart properly. ================================================================================ # Local tops and bottoms in the order book: what four trained models actually see URL: https://marketflowresear.ch/articles/local-tops-and-bottoms-what-four-trained-models-actually-see/ Published: 2026-08-06 · Series: Order-book research · Pivots > We marked every local top and bottom on 171 days of per-second Bitcoin order-book data — 734 of them, defined by a rule rather than by hand — and asked four trained market-state detectors whether they can see them. The zone itself is invisible. The moment of the extremum is not, and neither is 'an extremum within the next hour'. But a plain price range from the same window beats the order book at both, and the honest edge turns out to live somewhere else entirely: in telling a top from a bottom when price itself has nothing to say. ## ① What we marked, and why exactly this way A local top is not a point on a chart — it is a place where price stops going up and starts going down. To find those places without hand-picking them, we use a ZigZag with a 1.0% threshold: a new extremum is registered only once price has moved away from it by at least that much. By construction, both legs — to the previous extremum and to the next one — are at least 1.0% long, and we verify both explicitly, so the first and last pivot (whose legs are unfinished) are dropped. A **zone** is not the pivot itself. It is the longest continuous stretch around the extremum during which price stays inside a 0.5% band of it: for a top, not lower; for a bottom, not higher. That gives every extremum a duration, and duration turns out to matter more than anything else in this study. On our slice — BTC, 171.0 days of per-second order-book data — that produced **734 zones**: 367 tops and 367 bottoms, 4.29 a day, covering 15.02% of all time. The median zone lasts 1598 seconds; the shortest is 0, the longest 59083. Two details that decide whether the whole thing is honest. First, price is taken from **real observations only** — 18% of our seconds are missing, and interpolating them manufactures fake local extrema exactly inside the gaps. Second, top zones and bottom zones **cannot overlap**: with legs of 1% and a band of 0.5%, the upper edge of a bottom zone is always below the lower edge of a top zone. That is arithmetic, not luck — but we still checked it, and found 0 overlaps. ## ② What it looks like up close Zoomed in to a few days, the structure is obvious to the eye: green boxes sit on the tops, red boxes on the bottoms, and between them are the legs — the moves of at least 1% that connect one extremum to the next. This picture is not decoration. It explains half of the results that follow. In a strong trend there are almost no zones, because price never comes back into the band. In a range they cluster into grapes. Any statement about "how often the market is at an extremum" is really a statement about how trending the period was. ## ③ Can four trained models see a zone? We have four market-state detectors from a separate line of work: **storm**, **class 2**, **calm** and **PCA-quiet**. Each takes the raw 8x210 matrix of one 210-second window and returns a probability. The question of this study: given those four answers — for one window, or for up to eight consecutive windows — can you tell that you are standing in a zone? Every number below is measured against two yardsticks, and without them none of it means anything. The first is a **null control**: the model answers are circularly shifted in time, which destroys the link to the market but keeps their autocorrelation. The second is **plain price from the same window**. Validation is by 12-hour blocks with a one-hour embargo, because neighbouring windows correlate at about 0.76 and a random split would inflate everything. | task | four models | null | price range | |---|---|---|---| | inside any zone | 0.545 | 0.505 | 0.523 | | **the moment of the extremum** | **0.859** | 0.526 | 0.872 | | extremum within 3.5 minutes | 0.826 | 0.504 | 0.834 | | **an extremum in the next hour** | **0.748** | 0.506 | 0.715 | | top versus bottom | 0.527 | 0.500 | — | The answer splits into three. **The zone itself is invisible** — it lasts tens of minutes and for most of that time the market is simply asleep, so the label smears a short burst over a long stretch. **The moment of the extremum is marked sharply**, and there is even a genuinely predictive part: "an extremum will happen in the next hour" scores 0.748 against a null of 0.506. And then the honest part. A plain price range from the same window scores 0.872 on that same moment — it **beats the order book** — and putting them together adds about +0.005 AUC. The one place where the two are not interchangeable is direction: price *position* (its percentile over the trailing 24 hours) scores 0.689 on "top or bottom" but only 0.566 on "is this a zone at all". Price tells you the side. The order book tells you the moment. ## ④ Where the real hooks are Instead of one question we asked five, and the useful answers are all in the details. **The order book marks the edges of a zone, not the zone.** Inside a zone the storm probability starts high, collapses below baseline in the middle, and rises again at the exit. That makes sense: a zone is bounded by two moves of at least 1%, one arriving and one leaving, and those are what the model sees. **It only works on sharp zones.** At the level of whole zones rather than windows, the storm signal touched 50% of all 734 extrema in exactly their own window, where chance would give 10%. But split by duration: the tercile of short zones (median 462 s) is covered **57%** of the time, while the tercile of long ones (median 5059 s) is covered only 18% — worse than the 25% you would get at random. A spike is detectable. A slow plateau is not. **Sequence beats a single reading.** The rule "a storm window, then k quiet ones" fires 0.5% of the time and multiplies the chance of being in a zone by **1.208**. Calm on its own, without a storm before it, gives 0.997 — nothing. And the same sandwich built on price range at the same firing rate gives only 1.02-1.29. This is one of the few places in the whole study where the order book is genuinely ahead of price. **One trap worth naming.** Ninety within-window descriptors predict "top or bottom" at AUC 0.91, which looks like a breakthrough until you check price: price alone gives 0.994, and price plus order book gives the same 0.994. The descriptors were re-reading the direction of the impulse from flow asymmetry. Every apparent edge in this field needs a price yardstick standing next to it. ## ⑤ Two chains: everything after which price fell, against everything after which it rose We stitched all the top pieces into one chain and all the bottom pieces into another, then compared them feature by feature. The trap here is that feature levels drift across months far more than they differ between tops and bottoms, so every comparison is done **pairwise** — each top against its neighbouring bottom, which sits hours away rather than months — with a Benjamini-Hochberg correction on top. The strongest difference is trade volume: buys dominate at tops, sells at bottoms, by a wide margin. And it is worth **nothing**, which we only learned from a second control: for every piece we took a piece of equal length from the middle of the leg that led into it. Against that control the volume asymmetry at a top does not move at all (delta +0.001, p=0.96). Buyers at the top are buying exactly as they were on the whole way up. There is no exhaustion; the asymmetry is a shadow of the trend. What does survive the control is the **walls**. Inflow to the resistance side runs at +0.010 in the body of a rise and jumps to +0.079 inside the top zone; on the way down it runs at +0.065 and drops to +0.021 inside the bottom zone. Two shifts in **opposite** directions, both significant. The mechanism is the plainest one imaginable: at a top the sellers' wall grows, at a bottom the buyers' wall does. Something gets in the way, and the move stops. Size, honestly: about a 7% shift in log ratio. On the task of telling an extremum piece from a mid-leg piece it is worth 0.579, while price (move plus range) is worth 0.919 — and price plus order book is still 0.919. This is a confirming feature, not a signal on its own. Tops also last measurably longer than bottoms: a paired difference of +91 seconds. ## ⑥ The same signal in four different market states Every 210-second window belongs, by its midpoint, to one of four states: a top zone, a bottom zone, the body of an up leg, or the body of a down leg. The distribution of the storm probability is strongly bimodal — the median is near zero everywhere and the mass sits at the edges — so what has to be compared is the firing rate, not the median. | state | share of time | storm fires | vs base | |---|---|---|---| | bottom zone | 7.2% | 11.9% | x1.274 | | top zone | 7.9% | 11.7% | x1.257 | | down leg | 39.9% | 10.0% | x1.069 | | up leg | 44.6% | 8.0% | x0.852 | Tops and bottoms are indistinguishable — that is now the fourth independent way we have got the same result. Down legs against up legs, however, differ significantly and survive the within-day correction: falls are stormier than rises. Note where that directional tilt lives — in the **body of the move**, not at its ends. Along a leg the profile is U-shaped: the storm sits at both ends of a move and goes quiet in the middle, and on the way down it ramps up earlier and more steeply than on the way up. Read backwards, this is the entire practical value of the signal. When the storm detector fires, the chance of being in an extremum zone rises from 15.1% to 19.1%, and among legs the share of "down" rises from 47.2% to 52.8%. Three percentage points of directional tilt, against a round-trip fee of 0.30%, is not tradeable — and saying so is more useful than dressing it up. ## ⑦ Inside the classes: the 1680 numbers the network actually sees So far we compared what the network *said*. Here we compare what it *saw*: the 8x210 matrix in exactly the form it is fed in. For each of the four targets we take only its own windows and ask whether a storm at a top differs from a storm at a bottom — and whether the difference is in **levels** or in the **shape** inside the window. Each class answers differently, and that is the point: - **storm** separates tops from bottoms only by its walls: const_support +0.25, const_resist +0.17; - **class 2** has all six flows *lower* at tops — the book is busier at bottoms; - **calm** shows vol_sell +0.27 together with const_resist +0.23: in a quiet window at a top there is simultaneously a thicker sellers' wall and more selling; - **PCA-quiet** pushes that same signature to vol_sell **+0.67**, the largest effect in the entire study, though on only a few hundred windows. Shape works in exactly one class. Inside storm windows the slope of vol_buy differs at d = -0.23: at a top, buying **fades** across the 210 seconds; at a bottom it **builds**. In the quiet classes the slopes are empty — in a still window there is nothing to tilt, and all the information is in the level. And the single most important number in this article: on "top or bottom", price inside the same window scores 0.498 for storm, 0.459 for class 2, 0.484 for calm and 0.419 for PCA-quiet — nothing at all, in all four. The order book scores 0.52 to 0.59. It is modest, but it is not a shadow of price, and it now replicates across four independent subsamples. In an extremum price does not move for 210 seconds, so it has nothing to say; the book still does. ## ⑧ What this adds up to, and what comes next We have found classes, and they are real: found without supervision, reproduced by a second independently written pipeline, and detectable by trained models with out-of-fold AUC in the high 0.9s. That is the foundation for something practical — an **automated system for analysing the market state**, which is what all of this was leading to. We also see, plainly, that the classes behave differently in different market periods. The share of each class drifts across months; the same detector fires 3.8% of the time in one month and 17% in another. That is not a defect. It means the classes can be split into **subclasses** that describe the *current* state of the market — not forecasting anything, but making change itself observable. That drift is visible right on the charts of this study: the class-share panels move together with the regime of the market, and the last figures make it unmistakable. Everything in this project so far was done to learn — to find out what is in this data and, just as often, what is not. That part can now acquire a practical side: an **automatic market state detector**, running continuously, telling you which state you are in and when it changes. And we have built all of it so that you do not have to take our word for anything. Every study ships with a research diary that is an executable recipe: take your own data, run the commands in order, and get the same classes, the same numbers, the same trained models. Every user can reproduce these experiments and verify them personally. Stay with us and follow the articles that come next — they will have practical applications. The research diary of this study is published together with this article: [every command, every control, every tolerance and the complete code](PIVOTS_DIARY.md). The four market-state detectors used here are not our work in this study — they come from an earlier one, and that study has its own article and its own diary: [There Are No Classes in the Order Book](/articles/no-classes-in-the-order-book-only-one-state/). ================================================================================ # Four Market States, Found Twice by Two Independent Pipelines URL: https://marketflowresear.ch/articles/four-market-states-found-twice-by-two-independent-pipelines/ Published: 2026-08-06 · Series: Order-book research · Replication > Four market states, found twice by two pipelines that share no code. We wrote our research recipe down as an executable diary, then wrote a second implementation from that text alone — different seed, different block split, different network initialisation — and ran it over the same 54,764 windows of BTC order-book data. The states came back: 93.0% of windows landed in the same one (ARI 0.7726), and two independently trained detectors fire on the same 98.5% of windows. Where both fire, the next hour's price range is ×1.432 the median of the same day. ## ① The data both pipelines saw Everything below runs on one input: per-second order-book features for a single coin — wall thickness, inflow and drain on each side, and executed buy/sell volume. Eight numbers a second, 171 days of BTC, cut edge to edge into windows of 210 seconds. That gives 54,764 windows, 47,183 for training and 5,394 for validation, split in two-hour blocks with a 30-minute embargo between them — neighbouring windows are correlated, and a naive random split would leak a window's neighbour into validation. The rule that shapes the whole construction: **a window is classified by its own 1,680 numbers and nothing else**. No price, no time of day, no neighbouring windows, no rolling external norm. The only thing entering from outside is a scale constant computed on the training part. The next hour's price range is computed too, but it is an envelope opened after the state is already assigned — never an input. 18.4% of seconds are missing from the feed, so gaps are interpolated and any window with less than 95% real seconds is dropped. Two things were held identical between the two pipelines, both of them input/output rather than method: the CSV reader and the data boundary, so that both cut windows on exactly the same grid and a window-by-window comparison is possible at all. Everything arbitrary was changed: the seed (20260805 against 20260804), and with it the block split, the k-means initialisation, the fold assignment and every weight in the networks. ## ⑩ Four states: what the algorithm says, what the model says The line trains four production targets, and this is all four of them on one shared time axis. Green is the state as the algorithm assigned it; red is the state as a model trained on that assignment reads it back out of the raw 8 × 210 matrix. The engine on each panel is whichever of the two won cross-validation on PR-AUC. **Storm** — 10.3% of windows by the algorithm, 10.3% by the convolutional network, agreeing on 98.2% of windows (Jaccard 0.841). **Class 2** — 38.6% against 38.5%, 88.9% agreement. **Calm** — 51.1% against 51.0%, 93.5%. **PCA-quiet**, the fourth and rarest target, defined only where a 28-day norm already exists (hence the empty first four weeks) — 8.7% against 8.6%, 95.4% agreement but a Jaccard of only 0.5828: on a rare target most of that agreement is both sides staying silent, which is why the pair of columns has to be read together. Read this as a check that a model can recover the split from raw numbers, **not as a forecast**: these are production models, and 98% of the windows were in their training. The honest figures are the held-out 2%, cut as four contiguous chunks with an embargo — AUC 0.9976 and PR-AUC 0.9826 for storm, 0.9468 / 0.9589 for class 2, 0.964 / 0.9234 for calm, 0.9284 / 0.4812 for PCA-quiet. ## ⑪ Two independent runs across the whole history The top panel is the storm state as each pipeline assigned it, day by day, over the full 171 days; the bottom panel is the two detectors firing. The two lines track each other closely enough that they are hard to tell apart, which is the result — the second pipeline never saw the first one's code, only the text of the diary. In numbers: the states agree on 93.0% of 54,764 windows, ARI 0.7726. The shares match too — calm 51.1% against 51.9%, class 2 38.6% against 38.3%, storm 10.3% against 9.8%. Note that the raw cluster numbers agree far less (ARI 0.6702): k-means numbers its clusters however it likes, so the states must be named from the input side — by rank of total flow level — before anything is compared. ## ⑪ Twelve hours, window by window Close up, on a slice of history at the natural resolution of the method: four rows — my state, their state, my model's probability, their model's probability — over the same 210-second windows. This is the view where a replication either survives or falls apart, because agreement averaged over a day can hide two signals that fire at different moments. They don't: the two detectors light up on the same windows, with a Spearman correlation of 0.914 between their probabilities, Jaccard 0.856 and Cohen's κ 0.9141. Cross-wise it holds as well — my model against **their** state label agrees on 98.2% of windows, their model against mine on 97.8%. ## ⑪ Where the two runs disagree, and what price did next The left half is the state matrix — my run's rows against the other run's columns, as a share of all windows. The diagonal holds 93.0% of them. The right half asks the question a single model cannot answer: what happens in the off-diagonal cells? Where both detectors fire on storm — 8.9% of the time — the next hour's price range is ×1.432 the median of the same day (×1.865 in absolute terms, but the within-day correction is the honest one: without it you are measuring which month it is). Where only one fires, the edge mostly evaporates — ×1.143 for my model alone (1.3% of windows) and ×1.277 for theirs alone (0.2%). Where neither fires, ×0.976 — the market's own baseline. The useful object is not one detector's output; it is the region where two independently built detectors say the same thing. ## Conclusion: the states are real, and we are going to use them As we can see, the states are there. Two pipelines with nothing in common but a text file found the same four of them, in the same proportions, on the same windows — 93.0% agreement, ARI 0.7726 — and the detectors trained on those states by two different people-shaped processes fire together on 98.5% of the market's history. A structure that survives having its implementation thrown away and rewritten is a property of the order book, not of our code. Two of the states are sharper than the others, and we say so plainly: the boundary between the quiet states is a cut through a continuum — they blend — while **storm** is the one that stays sharp under every control we throw at it, including the one that matters most, the within-day correction: ×1.401 the next-hour range of its own day (×1.761 absolute). That is the state worth building on. So the work continues. Next we take these states out of the laboratory: a live detector reading the current window, agreement between two independent models as the actual trigger rather than one model's probability, and the same recipe run on the other five coins to see which parts travel. The full method — every command, every control, every tolerance and the complete code — is in the [research diary of this replication](MYWCLASS_DIARY.md), published alongside this article. The original line it was written from has its own article and its own diary: [There Are No Classes in the Order Book](/articles/no-classes-in-the-order-book-only-one-state/). Run it on your own data and tell us what came back. ================================================================================ # There Are No Classes in the Order Book — Only One State That Survives URL: https://marketflowresear.ch/articles/no-classes-in-the-order-book-only-one-state/ Published: 2026-08-05 · Series: Order-book research · Window classes > We locked a 210-second window to its own 1,680 numbers — eight order-book features, no norm, no price, no clock — and asked whether the market falls into classes. It does not: the gap statistic sits at 0.0017, silhouette matches noise, and at some K the shuffled null is more stable than the data. One state survives every check: 9.8% of windows where flows run hot and both walls thin out, followed by ×1.78 the usual hourly range. ## ① One window, 1,680 numbers, nothing else The constraint came first and everything follows from it: a 210-second window may be classified **only by its own 1,680 numbers** — eight order-book features across 210 seconds. No multi-day normalisation, no price, no time of day, no neighbouring windows. Anything computed from the dataset as a whole is outside information, and we later measured what dropping it costs — nothing at all. That leaves 54,764 windows cut edge to edge across 171 days. The map on the right is the shuffled null: cells permuted between windows, everything destroyed except the marginals. Note that the null grows its own detached blob — that is how easily a clustering pipeline invents a class. ## ② Before naming classes, ask whether classes exist Clustering always returns something, so the first job is to test the premise. Four independent criteria, each with its own null control run through the entire pipeline. The gap statistic at K=2 comes out at **0.0017** — a partition compresses the data no better than noise does. Silhouette on real data is **0.047** against **0.041** on the null. Silverman's test finds no second mode on any principal axis (smallest p = 0.19), nor along the direction of maximum separation. ## ③ Two respected criteria that lie here The bootstrap likelihood-ratio test rejects K=1 with LR = 23,673 against a null distribution of 123. Overwhelming — until you run the same test on shuffled cells, where it rejects K=1 just as confidently with LR = 14,117. It measures non-Gaussian marginals, not clusteredness. ICL behaves the same way: it falls monotonically to the largest K with no interior optimum. Stability is no safer. Rebuilding the whole pipeline on two disjoint halves of history gives ARI 0.50 at K=2 — and at K=5, 6 the **shuffled null is more stable than the real data**. A number that noise can beat is not evidence. ## ④ The structure is real — it just isn't classes None of this says the data is empty. Sixteen axes capture **83%** of the descriptor variance against **62%** on the null; on the raw 1,680-number vector it is 30.6% against 1.2%. The structure is simply continuous rather than discrete. A ladder of nulls locates it. Destroy the joint composition of features while keeping each feature's shape inside the window, and variance collapses from 83% to **63%**. Destroy everything else on top of that and you lose only another 1.0 points of variance. **What a window is, is what its features are doing together — not the shape they trace through time.** ## ⑤ Without an external norm, you classify the calendar Here is the trap that costs an entire study if missed. With no multi-day normalisation, the loudest signal in the data is the general activity level, and that drifts from month to month. Cramér's V between class label and month is **0.35**; one class holds 63% of the first half of history and a fraction of the second. So every price statement is measured twice: absolutely, and again **against the median of the same day**. Three of the four groups collapse from ×0.82…×1.15 to ×0.97…×0.98 — they were labels for a period of history. A distance-based forecast of the next hour's range drops from ρ = 0.593 to **ρ = 0.254** under the same correction, while the day's own level alone scores 0.605. ## ⑥ One state survives everything What is left is a single genuine state, and it is not subtle: **9.8% of windows** in which all six flow features run 1.4–1.9× their own scale while both resting walls sit *thinner* than normal. The book is coming apart while trade keeps running. Next-hour range after those windows is **×1.78** the typical, and **×1.40** even against other windows of the same day. On the held-out split alone it reads ×1.83 and ×1.47 — no worse than in training. This is a rediscovery, not a discovery. The same configuration was already validated in this project by two other routes. This pipeline reached it with no norm, no price and no clock. ## ⑦ Three comparisons you can run on any window The state distils into three thresholds on geometric feature levels — no model, no matrices, eight frozen constants and three numbers: **√(resist_minus · support_minus) > 1.417**, **√(resist_plus · support_plus) > 0.909**, **√(const_resist · const_support) < 1.234**. On held-out windows the rule fires 9.3% of the time with precision 0.773 and recall 0.662, and the following hour ranges ×2.08. Applied to 40,000 windows at **arbitrary offsets** — not aligned to any grid — it fires 8.6% of the time with the same ×1.94. Matching coverage on unaligned windows is the proof that this is a state of the market and not an artefact of how we sliced it. ## ⑧ Teaching a machine to see the same thing Four targets, input the full 8 × 210 raw matrix, transformed only inside the window. The dataset is cut into ten random parts; each window is scored exactly once by a model that never saw it. The convolutional network wins on every target and every fold — for the sharp state AUC 0.9968 (PR-AUC 0.9746). But the interesting part is the pattern across targets: against a plain linear model the network's edge is small on the sharp state and large on the blurred middle one. Sharp states live in levels; blurred ones live in shape. Two engines run in production, a network and gradient boosting. Across the whole dataset they agree on 98% of windows for the sharp state and only ~90% for the blurred ones — an independent confirmation, from a completely different direction, that the boundaries inside the continuum are conventions. ## ⑨ Reproduce it on your own data Everything above is a procedure, not a table of results. A class here is never a list of windows — it is defined by its rank in feature-flow level, so the same recipe recomputes it on another coin, another period, a longer history. The full research diary is attached: step by step how each class was found, which checks confirm or kill it, how the detectors were trained, plus the complete source of every file in the pipeline. Hand it to a machine together with your data and you get the same classes and working models back. [Download the research diary (WCLASS_DIARY.md)](WCLASS_DIARY.md) _Research, not financial advice. Written with AI assistance._ ================================================================================ # Event Classes Found Without a Teacher: 3 Survive, 60% Are Noise URL: https://marketflowresear.ch/articles/event-classes-found-without-a-teacher/ Published: 2026-08-03 · Series: Order-book research · Event classes > We asked the order book to sort its own events into classes — 2,786 events, eight features, no price and no human labels. Out of 512 configurations only 5 produced anything stable, 60% of events belong to no class at all, and the three that do exist raise volatility while leaving direction at a coin flip. ## ① Let the data name its own events Every earlier study started from a human definition: a spike is this, a wall is that. Here we did the opposite. We cut 2,786 events out of the archive, described each one as all 8 order-book features over a 210-second window, and handed that to an unsupervised pipeline — log transform, robust scaling, PCA, UMAP, then HDBSCAN. Price was not shown to the algorithm at any point; it only gets to comment afterwards. ## ② Most configurations find nothing — and that is the point Clustering will always return *something*, so the real work is deciding what to believe. We swept **512 configurations** and demanded stability, not beauty: only **5** survived the suitability filter. The winner explains 73% of input variance and lands on **k=3 classes** with bootstrap ARI 0.85 (sd 0.019). ## ③ Beating the shuffled null A stability number means nothing on its own, so we ran the same pipeline on time-shuffled and fully shuffled data. Real data: ARI 0.61 on the full bootstrap and 0.67 across folds. Shuffled null: 0.33. The gap is the whole claim of this study — the structure is in the book, not in the method. ## ④ Sixty percent of events belong to nothing The honest headline: **60% of events are noise** — HDBSCAN refuses to assign them to any class, and we do not force it. Only 40% form stable groups. A classifier that labelled everything would look far more impressive and be far less true. ## ⑤ The three classes that do exist What survives: **class 0** — 546 events (19.6%), led by drain out of the sell wall; **class 1** — 363 events (13.0%), led by the resting buy wall; **class 2** — 89 events (3.2%), led by the resting buy wall. The portraits show the median behaviour of all eight features through the event window, which is what actually separates the classes — one is dominated by liquidity leaving the book, the others by resting liquidity standing its ground. ## ⑥ How the classes differ, feature by feature The same difference stated as levels rather than curves: for each class, how far each feature sits from its own normal. This is the most compact description of what the algorithm found. ## ⑦ How long an event lasts Median event duration is 7.7 minutes, and the distribution is wide and skewed — the classes differ in duration as clearly as they differ in shape. ## ⑧ What happens after — the part price is allowed to answer Only now does price enter. Forward volatility after an event averages 0.0396 and the forward range 0.442, both meaningfully above the quiet baseline. Direction: **49.6% of events are followed by an up move** — a coin flip, again, on classes that were found without ever looking at price. ## ⑨ Where the classes sit on the price line The discovered classes drawn over the whole dataset, plus a zoom. Useful as a sanity check: the classes are not concentrated in one regime or one month. ## ⑩ Transitions between states Which state hands over to which, and how the sides balance inside each one. Note what is absent: no forecast is claimed here — transitions are a description of the sequence, not a prediction of it. _Research, not financial advice._ ================================================================================ # The Alphabet of the Order Book: 6,561 Possible States, 333 Real Ones URL: https://marketflowresear.ch/articles/the-alphabet-of-the-order-book-signal-states/ Published: 2026-08-03 · Series: Order-book research · Signals > We described the order book as a single word: eight features, three states each. Of the 6,561 words that could exist, only 333 ever occur — and when we tested that alphabet out of sample, it described the market well and predicted it poorly. ## ① A signal is a state of the whole book, not one number We stopped looking at features one at a time. At every moment each of the 8 order-book features is in one of three states — spike, normal or lull — so the market's condition is an eight-character word. That gives 6,561 possible words, of which only **333** ever actually occur across 12,477 observed windows. The book does not wander freely; it lives in a small corner of its own state space. ## ② Most of the time, nothing is happening One word dominates everything: all-normal, every feature quiet at once. It covers 6,351 of 12,477 windows — about 51% of the time — and its forward move is the smallest in the set (median 0.097%, up-share 49%). Any rule that fires on 'the market is doing something' has to first accept that four windows in five, it isn't. ## ③ What an active state looks like The most common non-quiet word is `01101111` — 864 windows. Its median absolute move is 0.142% against 0.097% for the quiet state, i.e. roughly ×1.5 more movement, while its up-share sits at 48% — near a coin flip. The pattern repeats at every level of this project: state tells you the amplitude, not the sign. ## ④ One feature alone versus several at once An isolated signal is one feature leaving its baseline while the other seven stay normal. They are informative in a narrow way: the strongest directional tilt belongs to **executed sell volume** (median -0.204%, up-share 18%, n=103), and the largest forward movement to **build-up into the buy wall** (median 0.250%). When several features fire together the move grows but the direction does not clarify. ## ⑤ How fast the information dies Every signal has a shelf life. Measured across horizons 5s, 60s, 5m, 1h, the advantage is concentrated in the first minutes and is gone well before the hour mark — consistent with the volatility studies, where flow-based edge decayed on the same clock. ## ⑥ The states drawn over price Rather than trusting the labels, look at them: the state sequence laid directly over BTC price. Long stretches of quiet, bursts where several features light up at once, and the price behaviour around those bursts. ## ⑦ The honest test: does it survive out of sample? This is the section that matters. We split the history in half, learned the behaviour of each state on the first part (6,238 windows) and applied it blind to the second (6,239). Direction AUC falls from **0.623 in-sample to 0.554 out-of-sample**; the 'will it move at all' model falls from 0.576 to 0.492 — i.e. to a coin flip. And 304 state-words in the test half had never been seen in training at all.\n\nSo the classification is real as a description and weak as a predictor. We publish it because the negative result is the finding: the book's state space is small and legible, but knowing today's word barely improves tomorrow's guess. ## ⑧ What we take from this Three things. The market's state space is far smaller than it could be — 333 words out of 6,561. Quiet dominates, so any live rule spends most of its time doing nothing. And the part that survives out of sample is amplitude, never direction — the same boundary we hit from every other angle in this project.\n\n_Research, not financial advice._ ================================================================================ # From Calm to Calm: a Standard for What Counts as a Signal (BTC) URL: https://marketflowresear.ch/articles/signal-standard-from-calm-to-calm-btc/ Published: 2026-08-03 · Series: Order-book research · Signal standard · BTC > We stopped defining market signals with a stopwatch. A signal is a continuous departure from calm, bounded by calm on both sides — the market decides where it starts and ends. Here is the standard, applied second by second to 167 days of BTC, with every event classified and located on the price path. ## ① A signal is what sits between two calms Most signal definitions start with a stopwatch: look at the last fifteen minutes, the last hour, the last day. The market does not run on our clock. So we let it draw its own boundaries. Each of the eight order-book features gets a rolling **100-hour norm** — its own average over the recent past, nothing forward-looking. The market is **calm** when no feature is more than 50% above its norm and the aggregate has not collapsed. A **signal** is everything in between two calms: it starts when the first feature leaves the band and ends only when all of them have been back inside for 5 minutes. One continuous burst, however long it lasts — never a fixed window. ## ② What "normal" actually means Our first definition of normal was "every feature within ±5% of its 100-hour average". That band turns out to be empty: it covers **0.00%** of all time. Order-book features are heavy-tailed — a five-minute level routinely swings tens of percent while nothing notable happens — so the band has to be measured, not assumed. Calibrating on the whole dataset puts the working threshold at **+50%** over the norm, which leaves the market calm **47%** of the time. Roughly half the clock is ordinary, half is events. That balance is what makes the two states worth comparing at all. ## ③ The anatomy of one event Here is a single signal, drawn as multiples of each feature's own norm. Everything starts flat near 1×, one or more features lift off, the burst runs, and the event closes only when the whole book has settled back. On BTC we find **2788 events** over 167 days: **897 bursts** (a peak of at least 3× the norm), 283 lulls (activity draining below normal) and 1608 minor wobbles that left calm without ever becoming a burst. Bursts alone come at **5.37 per day**, and all events together occupy 35% of the clock. ## ④ Duration is the first axis Event length spans three orders of magnitude, so we cut it into terciles measured on this coin: short (up to 13 min), medium (to 30 min) and long. The distribution is strongly skewed — most signals are minutes, a few run for hours, and the longest class (INFL·L·3) has a median of 186 minutes. Duration is not a cosmetic label: it is the axis that separates a passing flurry from a regime that the book sustains, and later it turns out to matter for where the event sits on the price path. ## ⑤ The class system Each event is labelled `LEADER-GROUP · DURATION · INTENSITY`. The leader group is whichever family deviated most from its own norm: the resting walls (`WALL`), inflow into them (`INFL`), drain out of them (`DRAIN`), or executed volume (`VOL`). Intensity is the peak over norm, again in terciles. That gives 35 populated burst classes on BTC, led by **VOL·S·1** with 109 events (median 7 min, peak 3.5× norm). Alongside the label, every event carries its full passport — mean per-second level of all eight features, their peaks, their totals over the event, and which side of each feature pair dominated. ## ⑥ Who leads the burst Executed volume leads most events — `VOL` heads 539 bursts against 141 for the walls, 130 for drain and 87 for inflow. That is the expected order: trades move faster than resting liquidity. The more interesting split is inside the volume family. Bursts led by buy volume and bursts led by sell volume are almost equally common, but they are not interchangeable — as the next section shows, they sit in very different places on the price path. ## ⑦ Pair dominance, measured against each feature's own norm Inside each pair we ask who deviated more — but relative to its own norm, not in raw size. Raw comparison would be useless: inflow is nearly always bigger than drain in absolute terms, so the "winner" would be fixed in advance. Normalised, the four pairs split into genuine contests: buy vs sell volume, support wall vs resistance wall, inflow vs drain on each side. This is the part of the passport that carries direction information — the rest of the passport is about size. ## ⑧ Where each class shows up Now the location test. A ZigZag with a 1.2% reversal threshold splits the history into 213 rising stretches (1986 h) and 214 falling ones (2013 h) — almost exactly balanced, so counts can be compared directly. Every event is assigned to the stretch containing its midpoint, and each class is tested against the share of rising time with a binomial test, Benjamini-Hochberg corrected. Rates are also reported per 100 hours of rising and of falling time, because raw counts would otherwise reward whichever regime lasted longer. ## ⑨ What actually separates rising from falling The location test is blunt about which parts of the passport carry information: bursts where **buy volume** deviated more sit in rising stretches 64% of the time (n=373, q=0.000), while **sell-dominated** bursts sit there only 39% (n=353, q=0.000); the same split by leader: vol_buy-led 62% rising vs vol_sell-led 39%; **long** events lean rising (58%, n=299, q=0.008) while short and medium ones are a coin flip; bursts where inflow into the resistance wall outran its drain appear in rising stretches 66% of the time (n=113, q=0.003). Two of these are mechanical and we say so plainly — buy-led bursts live in rising stretches because buying is what makes a stretch rise. The non-obvious ones are duration and the inflow/drain balance: how *long* the book stays out of calm, and which side of a wall is being built rather than eaten, both separate rising from falling without referring to price at all. ## ⑩ The other half: the calm states Between any two events sits a calm state, and it deserves the same treatment. There are **4255** of them here, median **11 minutes**, together 47% of the clock. Each gets its own passport: how long it lasted, whether price drifted up or down while the book was quiet, what price did in the event before and the event after, and what the neighbouring calms did. Classes follow the same logic as events — `CALM · duration · direction` — with "flat" defined as the bottom tercile of absolute drift (0.045%), so a third of calms are flat by construction. Quiet is not empty: even the flat ones drift by hundredths of a percent, and the long ones carry a directional lean of about 0.14%. ## ⑪ Is there a lull before the storm? The folklore says a long silence charges the market up. On this data it does not: the correlation between how long the market stayed quiet and how big the next event's move turned out to be is ρ = -0.0369 (n = 2788) — indistinguishable from nothing; and grouped by tercile it even leans the wrong way: after the shortest calms (median 6 min) the next event moves 0.073%, after the longest (25 min) only 0.061%, with the share of true bursts flat at 32%; longer calm is also followed by a *shorter* event (ρ = -0.1346). What the calm state does carry is a weak tendency to reverse rather than continue: price drift during a calm is negatively related to the drift of the next calm (ρ = -0.0583, p = 0.000143) and to the move of the next event (ρ = -0.0686, p = 0.000287), and the transition matrix says the same — after an up-drifting calm the next calm falls 37% of the time against 34% rising, and after a down-drifting calm the next event goes up 39% versus 30% down. Flat is the stickiest state of all: a flat calm is followed by another flat calm 42% of the time. Quiet begets quiet; it does not accumulate pressure. ## ⑫ What this is not ZigZag pivots are known only after the reversal has happened, so "this class lives in rising stretches" describes the past — it is not a forecast and cannot be traded as one. Class-level skews are thin at the tails and mostly do not survive multiple-comparison correction; the slice-level tests are the honest layer. And this is one symbol. The definition, the calibration table, the passport and the class system are deliberately built to be identical on every market, so the next step is the same run on the remaining five coins — and the real question there is which classes keep their location preference and which turn out to be artefacts of a single market. ================================================================================ # Side Against Side: Resistance and Support Compared URL: https://marketflowresear.ch/articles/resistance-against-support/ Published: 2026-07-31 · Series: Order-book research · Side vs side > We put all six order-book features grouped into the resistance side and the support side into one study and asked how the pieces relate, which one leads, and what the combination predicts. Same boundary as always: it speaks about size, not side. ## ① The pieces, measured separately This study looks at all six order-book features grouped into the resistance side and the support side. Before combining anything we show each component on its own scale, per coin — otherwise a composite hides which part is actually doing the work. ## ② How the pieces relate Cross-correlation between the components, averaged over coins. The strongest pairs are buy-wall build-up vs buy-wall drain +0.92; sell-wall build-up vs sell-wall drain +0.92; sell-wall drain vs buy-wall drain +0.80. Numbers near zero matter as much as high ones: they say the two quantities carry independent information and can be combined without simply repeating each other. ## ③ Which one moves first Lagged correlation answers the ordering question: when one component shifts, does the other follow, and after how long? Profiles that peak away from zero lag indicate a lead-follow relationship rather than a coincidence. ## ④ What the combination predicts The same volatility sweep as in every study, now for the combined view: link strength against the size of the next move across horizons, per coin. As everywhere else, the usable signal sits at the short end and concerns magnitude. ## ⑤ Where it peaks The best window per coin for the combined reading. ## ⑥ Impact per unit Price impact per +1σ of each component, side by side — useful to see which piece carries the mechanical push and which is merely correlated with it. ## ⑦ States and transitions Labelled states for the combined reading, and how they hand over to one another. ## ⑧ Memory of the combination Autocorrelation of the combined reading by timeframe — the same stickiness we see in every single feature, preserved after combining. ## ⑨ Extremes How far above normal the extremes of this combination run. _Research, not financial advice._ ================================================================================ # Flow Against the Wall: When Volume Meets Resting Liquidity URL: https://marketflowresear.ch/articles/flow-against-the-wall/ Published: 2026-07-31 · Series: Order-book research · Flow vs wall > We put executed volume hitting the resting wall on the opposite side into one study and asked how the pieces relate, which one leads, and what the combination predicts. Same boundary as always: it speaks about size, not side. ## ① The pieces, measured separately This study looks at executed volume hitting the resting wall on the opposite side. Before combining anything we show each component on its own scale, per coin — otherwise a composite hides which part is actually doing the work. ## ② How the pieces relate Cross-correlation between the components, averaged over coins. The strongest pairs are buy volume vs sell volume +0.52; the sell wall vs sell volume +0.18; the sell wall vs the buy wall +0.17. Numbers near zero matter as much as high ones: they say the two quantities carry independent information and can be combined without simply repeating each other. ## ③ Which one moves first Lagged correlation answers the ordering question: when one component shifts, does the other follow, and after how long? Profiles that peak away from zero lag indicate a lead-follow relationship rather than a coincidence. ## ④ What the combination predicts The same volatility sweep as in every study, now for the combined view: link strength against the size of the next move across horizons, per coin. As everywhere else, the usable signal sits at the short end and concerns magnitude. ## ⑤ The 2×2: thin vs thick, quiet vs busy Splitting the market into four cells — flow low/high against the wall thin/thick — gives the cleanest statement of the interaction. Mean absolute move per cell: low/thin: 0.0099, low/thick: 0.0093, high/thin: 0.0139, high/thick: 0.0139. The gap between the busy and quiet rows is the effect; the gap between thin and thick columns is what the wall adds on top of it. ## ⑤ Where it peaks The best window per coin for the combined reading. ## ⑥ Impact per unit Price impact per +1σ of each component, side by side — useful to see which piece carries the mechanical push and which is merely correlated with it. ## ⑦ States and transitions Labelled states for the combined reading, and how they hand over to one another. ## ⑧ Memory of the combination Autocorrelation of the combined reading by timeframe — the same stickiness we see in every single feature, preserved after combining. ## ⑨ Extremes How far above normal the extremes of this combination run. _Research, not financial advice._ ================================================================================ # The Life of a Sell Wall: Standing, Growing, Thinning URL: https://marketflowresear.ch/articles/lifecycle-of-a-sell-wall/ Published: 2026-07-31 · Series: Order-book research · Wall lifecycle > We put the three phases of the same sell-side wall — how much stands there, what arrives, what leaves into one study and asked how the pieces relate, which one leads, and what the combination predicts. Same boundary as always: it speaks about size, not side. ## ① The pieces, measured separately This study looks at the three phases of the same sell-side wall — how much stands there, what arrives, what leaves. Before combining anything we show each component on its own scale, per coin — otherwise a composite hides which part is actually doing the work. ## ② How the pieces relate Cross-correlation between the components, averaged over coins. The strongest pairs are sell-wall build-up vs sell-wall drain +0.92; the sell wall vs sell-wall build-up +0.32; the sell wall vs sell-wall drain +0.26. Numbers near zero matter as much as high ones: they say the two quantities carry independent information and can be combined without simply repeating each other. ## ③ Which one moves first Lagged correlation answers the ordering question: when one component shifts, does the other follow, and after how long? Profiles that peak away from zero lag indicate a lead-follow relationship rather than a coincidence. ## ④ What the combination predicts The same volatility sweep as in every study, now for the combined view: link strength against the size of the next move across horizons, per coin. As everywhere else, the usable signal sits at the short end and concerns magnitude. ## ⑤ Where it peaks The best window per coin for the combined reading. ## ⑥ Impact per unit Price impact per +1σ of each component, side by side — useful to see which piece carries the mechanical push and which is merely correlated with it. ## ⑦ States and transitions Labelled states for the combined reading, and how they hand over to one another. ## ⑧ Memory of the combination Autocorrelation of the combined reading by timeframe — the same stickiness we see in every single feature, preserved after combining. ## ⑨ Extremes How far above normal the extremes of this combination run. _Research, not financial advice._ ================================================================================ # Executed Sell Volume, Measured Alone URL: https://marketflowresear.ch/articles/executed-sell-volume-alone/ Published: 2026-07-31 · Series: Order-book research · Sell volume > We isolated executed sell volume — one feature, no partner, no composite — and measured what it predicts second by second across six coins. The answer is the size of the next move, never its side. ## ① The shape of executed sell volume Before asking what executed sell volume predicts, we look at what it is: how the quantity is distributed across its own range, per coin. The profile is heavily skewed — long stretches of very little, punctuated by rare, very large readings. Every threshold later in the study is a quantile of this shape, not a round number picked by hand. ## ② What it predicts, across horizons Rank correlation of executed sell volume with the size of the next move peaks at the fastest horizon (+0.23 on ETH at 5s) and decays monotonically toward the daily scale (+0.02). Direction is a different story: the same sweep against signed returns tops out around 0.12. Size, yes; side, no. ## ③ Where each coin peaks The best window differs by coin but always sits at the short end — 5s to 5s. Anything slower than that is reading yesterday's news. ## ④ Price impact per unit Per +1σ of executed sell volume, price moves by a fraction of a basis point, and the sign is not stable across bands. This is the quantitative version of 'it does not push price in a usable direction'. ## ⑤ What counts as normal Normal levels of executed sell volume grow by orders of magnitude from a second to a day, so 'high' is always relative to a window. This chart is the baseline every later threshold is measured against. ## ⑥ Memory Autocorrelation of executed sell volume starts at 0.14–0.25 at the finest scale and rises to 0.57–0.67 at intermediate windows. The quantity clusters in time: a busy minute follows a busy minute far more often than chance allows. ## ⑦ Where the seconds live Most seconds carry almost no executed sell volume; the interesting behaviour is confined to a thin tail. Working with means here would describe a market that does not exist. ## ⑧ How large the extremes get A peak second of executed sell volume runs many times above its own normal. That ratio is what makes threshold rules feasible at all — the extremes are unmistakable once the baseline is right. ## ⑨ Spike, normal, lull Every moment gets labelled relative to its own baseline. The three states separate cleanly in volatility and poorly in direction — the same result the whole project keeps producing. ## ⑩ The states over price The labelling drawn directly over a BTC price window: where executed sell volume changes state, and what price does around it. _Research, not financial advice._ ================================================================================ # Executed Buy Volume, Measured Alone URL: https://marketflowresear.ch/articles/executed-buy-volume-alone/ Published: 2026-07-31 · Series: Order-book research · Buy volume > We isolated executed buy volume — one feature, no partner, no composite — and measured what it predicts second by second across six coins. The answer is the size of the next move, never its side. ## ① The shape of executed buy volume Before asking what executed buy volume predicts, we look at what it is: how the quantity is distributed across its own range, per coin. The profile is heavily skewed — long stretches of very little, punctuated by rare, very large readings. Every threshold later in the study is a quantile of this shape, not a round number picked by hand. ## ② What it predicts, across horizons Rank correlation of executed buy volume with the size of the next move peaks at the fastest horizon (+0.25 on ETH at 5s) and decays monotonically toward the daily scale (+0.04). Direction is a different story: the same sweep against signed returns tops out around 0.12. Size, yes; side, no. ## ③ Where each coin peaks The best window differs by coin but always sits at the short end — 5s to 5s. Anything slower than that is reading yesterday's news. ## ④ Price impact per unit Per +1σ of executed buy volume, price moves by a fraction of a basis point, and the sign is not stable across bands. This is the quantitative version of 'it does not push price in a usable direction'. ## ⑤ What counts as normal Normal levels of executed buy volume grow by orders of magnitude from a second to a day, so 'high' is always relative to a window. This chart is the baseline every later threshold is measured against. ## ⑥ Memory Autocorrelation of executed buy volume starts at 0.14–0.24 at the finest scale and rises to 0.57–0.67 at intermediate windows. The quantity clusters in time: a busy minute follows a busy minute far more often than chance allows. ## ⑦ Where the seconds live Most seconds carry almost no executed buy volume; the interesting behaviour is confined to a thin tail. Working with means here would describe a market that does not exist. ## ⑧ How large the extremes get A peak second of executed buy volume runs many times above its own normal. That ratio is what makes threshold rules feasible at all — the extremes are unmistakable once the baseline is right. ## ⑨ Spike, normal, lull Every moment gets labelled relative to its own baseline. The three states separate cleanly in volatility and poorly in direction — the same result the whole project keeps producing. ## ⑩ The states over price The labelling drawn directly over a BTC price window: where executed buy volume changes state, and what price does around it. _Research, not financial advice._ ================================================================================ # Drain Out of the Buy Wall: Liquidity Leaving Before the Move URL: https://marketflowresear.ch/articles/drain-out-of-the-buy-wall/ Published: 2026-07-31 · Series: Order-book research · Buy drain > We isolated drain out of the buy wall — one feature, no partner, no composite — and measured what it predicts second by second across six coins. The answer is the size of the next move, never its side. ## ① The shape of drain out of the buy wall Before asking what drain out of the buy wall predicts, we look at what it is: how the quantity is distributed across its own range, per coin. The profile is heavily skewed — long stretches of very little, punctuated by rare, very large readings. Every threshold later in the study is a quantile of this shape, not a round number picked by hand. ## ② What it predicts, across horizons Rank correlation of drain out of the buy wall with the size of the next move peaks at the fastest horizon (+0.36 on BTC at 5s) and decays monotonically toward the daily scale (+0.07). Direction is a different story: the same sweep against signed returns tops out around 0.06. Size, yes; side, no. ## ③ Where each coin peaks The best window differs by coin but always sits at the short end — 5s to 5s. Anything slower than that is reading yesterday's news. ## ④ Price impact per unit Per +1σ of drain out of the buy wall, price moves by a fraction of a basis point, and the sign is not stable across bands. This is the quantitative version of 'it does not push price in a usable direction'. ## ⑤ What counts as normal Normal levels of drain out of the buy wall grow by orders of magnitude from a second to a day, so 'high' is always relative to a window. This chart is the baseline every later threshold is measured against. ## ⑥ Memory Autocorrelation of drain out of the buy wall starts at 0.29–0.44 at the finest scale and rises to 0.76–0.82 at intermediate windows. The quantity clusters in time: a busy minute follows a busy minute far more often than chance allows. ## ⑦ Where the seconds live Most seconds carry almost no drain out of the buy wall; the interesting behaviour is confined to a thin tail. Working with means here would describe a market that does not exist. ## ⑧ How large the extremes get A peak second of drain out of the buy wall runs many times above its own normal. That ratio is what makes threshold rules feasible at all — the extremes are unmistakable once the baseline is right. ## ⑨ Spike, normal, lull Every moment gets labelled relative to its own baseline. The three states separate cleanly in volatility and poorly in direction — the same result the whole project keeps producing. ## ⑩ The states over price The labelling drawn directly over a BTC price window: where drain out of the buy wall changes state, and what price does around it. _Research, not financial advice._ ================================================================================ # Build-Up Into the Buy Wall: What Arriving Liquidity Predicts URL: https://marketflowresear.ch/articles/build-up-into-the-buy-wall/ Published: 2026-07-31 · Series: Order-book research · Buy build-up > We isolated build-up into the buy wall — one feature, no partner, no composite — and measured what it predicts second by second across six coins. The answer is the size of the next move, never its side. ## ① The shape of build-up into the buy wall Before asking what build-up into the buy wall predicts, we look at what it is: how the quantity is distributed across its own range, per coin. The profile is heavily skewed — long stretches of very little, punctuated by rare, very large readings. Every threshold later in the study is a quantile of this shape, not a round number picked by hand. ## ② What it predicts, across horizons Rank correlation of build-up into the buy wall with the size of the next move peaks at the fastest horizon (+0.38 on BTC at 5s) and decays monotonically toward the daily scale (+0.06). Direction is a different story: the same sweep against signed returns tops out around 0.10. Size, yes; side, no. ## ③ Where each coin peaks The best window differs by coin but always sits at the short end — 5s to 5s. Anything slower than that is reading yesterday's news. ## ④ Price impact per unit Per +1σ of build-up into the buy wall, price moves by a fraction of a basis point, and the sign is not stable across bands. This is the quantitative version of 'it does not push price in a usable direction'. ## ⑤ What counts as normal Normal levels of build-up into the buy wall grow by orders of magnitude from a second to a day, so 'high' is always relative to a window. This chart is the baseline every later threshold is measured against. ## ⑥ Memory Autocorrelation of build-up into the buy wall starts at 0.29–0.46 at the finest scale and rises to 0.77–0.82 at intermediate windows. The quantity clusters in time: a busy minute follows a busy minute far more often than chance allows. ## ⑦ Where the seconds live Most seconds carry almost no build-up into the buy wall; the interesting behaviour is confined to a thin tail. Working with means here would describe a market that does not exist. ## ⑧ How large the extremes get A peak second of build-up into the buy wall runs many times above its own normal. That ratio is what makes threshold rules feasible at all — the extremes are unmistakable once the baseline is right. ## ⑨ Spike, normal, lull Every moment gets labelled relative to its own baseline. The three states separate cleanly in volatility and poorly in direction — the same result the whole project keeps producing. ## ⑩ The states over price The labelling drawn directly over a BTC price window: where build-up into the buy wall changes state, and what price does around it. _Research, not financial advice._ ================================================================================ # Drain Out of the Sell Wall: Liquidity Leaving Before the Move URL: https://marketflowresear.ch/articles/drain-out-of-the-sell-wall/ Published: 2026-07-31 · Series: Order-book research · Sell drain > We isolated drain out of the sell wall — one feature, no partner, no composite — and measured what it predicts second by second across six coins. The answer is the size of the next move, never its side. ## ① The shape of drain out of the sell wall Before asking what drain out of the sell wall predicts, we look at what it is: how the quantity is distributed across its own range, per coin. The profile is heavily skewed — long stretches of very little, punctuated by rare, very large readings. Every threshold later in the study is a quantile of this shape, not a round number picked by hand. ## ② What it predicts, across horizons Rank correlation of drain out of the sell wall with the size of the next move peaks at the fastest horizon (+0.37 on BTC at 5s) and decays monotonically toward the daily scale (+0.07). Direction is a different story: the same sweep against signed returns tops out around 0.05. Size, yes; side, no. ## ③ Where each coin peaks The best window differs by coin but always sits at the short end — 5s to 5s. Anything slower than that is reading yesterday's news. ## ④ Price impact per unit Per +1σ of drain out of the sell wall, price moves by a fraction of a basis point, and the sign is not stable across bands. This is the quantitative version of 'it does not push price in a usable direction'. ## ⑤ What counts as normal Normal levels of drain out of the sell wall grow by orders of magnitude from a second to a day, so 'high' is always relative to a window. This chart is the baseline every later threshold is measured against. ## ⑥ Memory Autocorrelation of drain out of the sell wall starts at 0.29–0.45 at the finest scale and rises to 0.75–0.82 at intermediate windows. The quantity clusters in time: a busy minute follows a busy minute far more often than chance allows. ## ⑦ Where the seconds live Most seconds carry almost no drain out of the sell wall; the interesting behaviour is confined to a thin tail. Working with means here would describe a market that does not exist. ## ⑧ How large the extremes get A peak second of drain out of the sell wall runs many times above its own normal. That ratio is what makes threshold rules feasible at all — the extremes are unmistakable once the baseline is right. ## ⑨ Spike, normal, lull Every moment gets labelled relative to its own baseline. The three states separate cleanly in volatility and poorly in direction — the same result the whole project keeps producing. ## ⑩ The states over price The labelling drawn directly over a BTC price window: where drain out of the sell wall changes state, and what price does around it. _Research, not financial advice._ ================================================================================ # Build-Up Into the Sell Wall: What Arriving Liquidity Predicts URL: https://marketflowresear.ch/articles/build-up-into-the-sell-wall/ Published: 2026-07-31 · Series: Order-book research · Sell build-up > We isolated build-up into the sell wall — one feature, no partner, no composite — and measured what it predicts second by second across six coins. The answer is the size of the next move, never its side. ## ① The shape of build-up into the sell wall Before asking what build-up into the sell wall predicts, we look at what it is: how the quantity is distributed across its own range, per coin. The profile is heavily skewed — long stretches of very little, punctuated by rare, very large readings. Every threshold later in the study is a quantile of this shape, not a round number picked by hand. ## ② What it predicts, across horizons Rank correlation of build-up into the sell wall with the size of the next move peaks at the fastest horizon (+0.38 on BTC at 5s) and decays monotonically toward the daily scale (+0.07). Direction is a different story: the same sweep against signed returns tops out around 0.10. Size, yes; side, no. ## ③ Where each coin peaks The best window differs by coin but always sits at the short end — 5s to 5s. Anything slower than that is reading yesterday's news. ## ④ Price impact per unit Per +1σ of build-up into the sell wall, price moves by a fraction of a basis point, and the sign is not stable across bands. This is the quantitative version of 'it does not push price in a usable direction'. ## ⑤ What counts as normal Normal levels of build-up into the sell wall grow by orders of magnitude from a second to a day, so 'high' is always relative to a window. This chart is the baseline every later threshold is measured against. ## ⑥ Memory Autocorrelation of build-up into the sell wall starts at 0.31–0.46 at the finest scale and rises to 0.77–0.83 at intermediate windows. The quantity clusters in time: a busy minute follows a busy minute far more often than chance allows. ## ⑦ Where the seconds live Most seconds carry almost no build-up into the sell wall; the interesting behaviour is confined to a thin tail. Working with means here would describe a market that does not exist. ## ⑧ How large the extremes get A peak second of build-up into the sell wall runs many times above its own normal. That ratio is what makes threshold rules feasible at all — the extremes are unmistakable once the baseline is right. ## ⑨ Spike, normal, lull Every moment gets labelled relative to its own baseline. The three states separate cleanly in volatility and poorly in direction — the same result the whole project keeps producing. ## ⑩ The states over price The labelling drawn directly over a BTC price window: where build-up into the sell wall changes state, and what price does around it. _Research, not financial advice._ ================================================================================ # The Resting Buy Wall, Measured Alone URL: https://marketflowresear.ch/articles/the-resting-buy-wall-alone/ Published: 2026-07-31 · Series: Order-book research · Buy wall > We isolated the resting buy wall — one feature, no partner, no composite — and measured what it predicts second by second across six coins. The answer is the size of the next move, never its side. ## ① The shape of the resting buy wall Before asking what the resting buy wall predicts, we look at what it is: how the quantity is distributed across its own range, per coin. The profile is heavily skewed — long stretches of very little, punctuated by rare, very large readings. Every threshold later in the study is a quantile of this shape, not a round number picked by hand. ## ② What it predicts, across horizons Rank correlation of the resting buy wall with the size of the next move peaks at the fastest horizon (-0.08 on BTC at 5s) and decays monotonically toward the daily scale (-0.03). Direction is a different story: the same sweep against signed returns tops out around 0.29. Size, yes; side, no. ## ③ Where each coin peaks The best window differs by coin but always sits at the short end — 5s to 86400s. Anything slower than that is reading yesterday's news. ## ④ Price impact per unit Per +1σ of the resting buy wall, price moves by a fraction of a basis point, and the sign is not stable across bands. This is the quantitative version of 'it does not push price in a usable direction'. ## ⑤ What counts as normal Normal levels of the resting buy wall grow by orders of magnitude from a second to a day, so 'high' is always relative to a window. This chart is the baseline every later threshold is measured against. ## ⑥ Memory Autocorrelation of the resting buy wall starts at 0.67–0.80 at the finest scale and rises to 0.73–0.91 at intermediate windows. The quantity clusters in time: a busy minute follows a busy minute far more often than chance allows. ## ⑦ Where the seconds live Most seconds carry almost no the resting buy wall; the interesting behaviour is confined to a thin tail. Working with means here would describe a market that does not exist. ## ⑧ How large the extremes get A peak second of the resting buy wall runs many times above its own normal. That ratio is what makes threshold rules feasible at all — the extremes are unmistakable once the baseline is right. ## ⑨ Spike, normal, lull Every moment gets labelled relative to its own baseline. The three states separate cleanly in volatility and poorly in direction — the same result the whole project keeps producing. ## ⑩ The states over price The labelling drawn directly over a BTC price window: where the resting buy wall changes state, and what price does around it. _Research, not financial advice._ ================================================================================ # The Resting Sell Wall, Measured Alone URL: https://marketflowresear.ch/articles/the-resting-sell-wall-alone/ Published: 2026-07-31 · Series: Order-book research · Sell wall > We isolated the resting sell wall — one feature, no partner, no composite — and measured what it predicts second by second across six coins. The answer is the size of the next move, never its side. ## ① The shape of the resting sell wall Before asking what the resting sell wall predicts, we look at what it is: how the quantity is distributed across its own range, per coin. The profile is heavily skewed — long stretches of very little, punctuated by rare, very large readings. Every threshold later in the study is a quantile of this shape, not a round number picked by hand. ## ② What it predicts, across horizons Rank correlation of the resting sell wall with the size of the next move peaks at the fastest horizon (-0.08 on BTC at 5s) and decays monotonically toward the daily scale (-0.04). Direction is a different story: the same sweep against signed returns tops out around 0.29. Size, yes; side, no. ## ③ Where each coin peaks The best window differs by coin but always sits at the short end — 5s to 86400s. Anything slower than that is reading yesterday's news. ## ④ Price impact per unit Per +1σ of the resting sell wall, price moves by a fraction of a basis point, and the sign is not stable across bands. This is the quantitative version of 'it does not push price in a usable direction'. ## ⑤ What counts as normal Normal levels of the resting sell wall grow by orders of magnitude from a second to a day, so 'high' is always relative to a window. This chart is the baseline every later threshold is measured against. ## ⑥ Memory Autocorrelation of the resting sell wall starts at 0.68–0.80 at the finest scale and rises to 0.75–0.86 at intermediate windows. The quantity clusters in time: a busy minute follows a busy minute far more often than chance allows. ## ⑦ Where the seconds live Most seconds carry almost no the resting sell wall; the interesting behaviour is confined to a thin tail. Working with means here would describe a market that does not exist. ## ⑧ How large the extremes get A peak second of the resting sell wall runs many times above its own normal. That ratio is what makes threshold rules feasible at all — the extremes are unmistakable once the baseline is right. ## ⑨ Spike, normal, lull Every moment gets labelled relative to its own baseline. The three states separate cleanly in volatility and poorly in direction — the same result the whole project keeps producing. ## ⑩ The states over price The labelling drawn directly over a BTC price window: where the resting sell wall changes state, and what price does around it. _Research, not financial advice._ ================================================================================ # The Support Cycle: Liquidity Arriving vs Leaving URL: https://marketflowresear.ch/articles/support-cycle-build-up-versus-drain/ Published: 2026-07-31 · Series: Order-book research · Support cycle > We measured the same buy-side wall growing and thinning second by second across six coins, and asked the only question that matters: does it tell you anything about what happens next? It does — about size, not direction. ## ① Which side carries more of the support cycle Across the whole archive the two sides sit close together: the ratio between build-up into the buy wall and drain out of the buy wall runs 0.37–0.71× depending on the coin. Neither side structurally dominates the book — which matters, because it means anything we find later is about *changes* in the support cycle, not about a permanent imbalance between buyers and sellers. ## ② Does it predict the size of the next move This is the core question. Rank correlation with the size of the next move is **positive** on 6 of 6 coins, and strongest at the shortest horizon — +0.39 on BTC at 5s. By the daily scale it fades to +0.07. In plain terms: when the support cycle runs high, the following window tends to be more volatile than usual, and the effect strengthens as the window widens. ## ③ How much price actually moves per unit We measure the price shift per +1σ of the support cycle, split into low, middle and high bands. The effect is small in absolute terms — fractions of a basis point per σ — and asymmetric between the two sides. That asymmetry is worth knowing, but it is nowhere near a tradable directional push on its own. ## ④ What counts as normal, by timeframe 'Normal' has no absolute value here: the support cycle measured per second is a different quantity from the same thing aggregated over an hour or a day, and the scale grows by orders of magnitude (log axis). Every threshold we use later is therefore relative to its own window and its own coin — never a fixed number carried across timeframes. ## ⑤ Where the link peaks Each coin has a window where the support cycle lines up best with what follows, marked with a star. The peaks cluster at the short end — the information decays quickly, so any use of this signal has to act on the scale of seconds to minutes rather than hours. ## ⑥ Does the imbalance predict direction Barely. Taking the signed difference between build-up into the buy wall and drain out of the buy wall and correlating it with the direction of the next move gives at most ρ≈0.22 anywhere in the grid, and it collapses toward zero on most coins and most horizons. This mirrors what we found with volume: the book tells you how much, not which way. ## ⑦ How long one-sidedness survives A lopsided book does not stay lopsided. The share of imbalance that persists falls from about 51–63% at one second to roughly 16–45% by the twenty-minute mark. Whatever pushes the support cycle to one side is undone quickly — which is exactly why it cannot steer longer moves. ## ⑧ Memory: does a busy second predict a busy second Yes, and this is the most robust property in the whole study. Lag-1 autocorrelation of the support cycle is 0.36–0.49 at the fastest scale and 0.29–0.40 at the slowest, on every coin. The quantity is sticky: its own past is a better predictor of its near future than anything about price. ## ⑨ How extreme the extremes are Extremes are not mild. A peak second can carry many times the normal level of the support cycle, which is why averages describe this data badly and why we work with quantiles and episodes instead of means. ## ⑩ Where the seconds actually live Most seconds are unremarkable: the distribution of the support cycle is concentrated in the low bands with a long thin tail. The market spends the overwhelming majority of its time doing nothing interesting, and the tail is where every episode we care about comes from. ## ⑪ Spike, normal, lull — what each looks like We label every moment as spike, normal or lull relative to its own baseline, then look at how price behaves inside each state. The states differ from each other in volatility far more clearly than in direction — the same asymmetry that runs through the whole project. ## ⑫ The same states laid over price Here the labelling is placed directly on a price window so you can see it rather than trust it: where the support cycle flips state, and what price does around those flips. ## ⑬ Extremes arrive in clusters Spikes in the support cycle are not evenly spaced — they bunch into storms, and a spike inside a cluster is a different animal from an isolated one. Any threshold rule that ignores clustering will fire in bursts and then sit idle for hours. ## ⑭ What it forecasts, honestly Pulling it together: the two sides of the support cycle move together (coupling reaches 0.90–0.98 at the long end), the quantity forecasts its own future well, and it carries a positive signal about the *size* of the next move. What it does not carry — on any horizon we measured — is the side. That is the honest boundary of this study. _Research, not financial advice._ ================================================================================ # The Resistance Cycle: Liquidity Arriving vs Leaving URL: https://marketflowresear.ch/articles/resistance-cycle-build-up-versus-drain/ Published: 2026-07-31 · Series: Order-book research · Resistance cycle > We measured the same sell-side wall growing and thinning second by second across six coins, and asked the only question that matters: does it tell you anything about what happens next? It does — about size, not direction. ## ① Which side carries more of the resistance cycle Across the whole archive the two sides sit close together: the ratio between build-up into the sell wall and drain out of the sell wall runs 0.36–0.72× depending on the coin. Neither side structurally dominates the book — which matters, because it means anything we find later is about *changes* in the resistance cycle, not about a permanent imbalance between buyers and sellers. ## ② Does it predict the size of the next move This is the core question. Rank correlation with the size of the next move is **positive** on 6 of 6 coins, and strongest at the shortest horizon — +0.39 on BTC at 5s. By the daily scale it fades to +0.07. In plain terms: when the resistance cycle runs high, the following window tends to be more volatile than usual, and the effect strengthens as the window widens. ## ③ How much price actually moves per unit We measure the price shift per +1σ of the resistance cycle, split into low, middle and high bands. The effect is small in absolute terms — fractions of a basis point per σ — and asymmetric between the two sides. That asymmetry is worth knowing, but it is nowhere near a tradable directional push on its own. ## ④ What counts as normal, by timeframe 'Normal' has no absolute value here: the resistance cycle measured per second is a different quantity from the same thing aggregated over an hour or a day, and the scale grows by orders of magnitude (log axis). Every threshold we use later is therefore relative to its own window and its own coin — never a fixed number carried across timeframes. ## ⑤ Where the link peaks Each coin has a window where the resistance cycle lines up best with what follows, marked with a star. The peaks cluster at the short end — the information decays quickly, so any use of this signal has to act on the scale of seconds to minutes rather than hours. ## ⑥ Does the imbalance predict direction Barely. Taking the signed difference between build-up into the sell wall and drain out of the sell wall and correlating it with the direction of the next move gives at most ρ≈0.22 anywhere in the grid, and it collapses toward zero on most coins and most horizons. This mirrors what we found with volume: the book tells you how much, not which way. ## ⑦ How long one-sidedness survives A lopsided book does not stay lopsided. The share of imbalance that persists falls from about 51–63% at one second to roughly 16–46% by the twenty-minute mark. Whatever pushes the resistance cycle to one side is undone quickly — which is exactly why it cannot steer longer moves. ## ⑧ Memory: does a busy second predict a busy second Yes, and this is the most robust property in the whole study. Lag-1 autocorrelation of the resistance cycle is 0.36–0.49 at the fastest scale and 0.29–0.42 at the slowest, on every coin. The quantity is sticky: its own past is a better predictor of its near future than anything about price. ## ⑨ How extreme the extremes are Extremes are not mild. A peak second can carry many times the normal level of the resistance cycle, which is why averages describe this data badly and why we work with quantiles and episodes instead of means. ## ⑩ Where the seconds actually live Most seconds are unremarkable: the distribution of the resistance cycle is concentrated in the low bands with a long thin tail. The market spends the overwhelming majority of its time doing nothing interesting, and the tail is where every episode we care about comes from. ## ⑪ Spike, normal, lull — what each looks like We label every moment as spike, normal or lull relative to its own baseline, then look at how price behaves inside each state. The states differ from each other in volatility far more clearly than in direction — the same asymmetry that runs through the whole project. ## ⑫ The same states laid over price Here the labelling is placed directly on a price window so you can see it rather than trust it: where the resistance cycle flips state, and what price does around those flips. ## ⑬ Extremes arrive in clusters Spikes in the resistance cycle are not evenly spaced — they bunch into storms, and a spike inside a cluster is a different animal from an isolated one. Any threshold rule that ignores clustering will fire in bursts and then sit idle for hours. ## ⑭ What it forecasts, honestly Pulling it together: the two sides of the resistance cycle move together (coupling reaches 0.90–0.99 at the long end), the quantity forecasts its own future well, and it carries a positive signal about the *size* of the next move. What it does not carry — on any horizon we measured — is the side. That is the honest boundary of this study. _Research, not financial advice._ ================================================================================ # Liquidity Arriving: What a Growing Wall Says Next URL: https://marketflowresear.ch/articles/wall-build-up-liquidity-arriving/ Published: 2026-07-31 · Series: Order-book research · Inflow > We measured fresh resting liquidity arriving into the book second by second across six coins, and asked the only question that matters: does it tell you anything about what happens next? It does — about size, not direction. ## ① Which side carries more of wall build-up Across the whole archive the two sides sit close together: the ratio between the sell-wall build-up and the buy-wall build-up runs 0.94–1.03× depending on the coin. Neither side structurally dominates the book — which matters, because it means anything we find later is about *changes* in wall build-up, not about a permanent imbalance between buyers and sellers. ## ② Does it predict the size of the next move This is the core question. Rank correlation with the size of the next move is **positive** on 6 of 6 coins, and strongest at the shortest horizon — +0.43 on BTC at 5s. By the daily scale it fades to +0.07. In plain terms: when wall build-up runs high, the following window tends to be more volatile than usual, and the effect strengthens as the window widens. ## ③ How much price actually moves per unit We measure the price shift per +1σ of wall build-up, split into low, middle and high bands. The effect is small in absolute terms — fractions of a basis point per σ — and asymmetric between the two sides. That asymmetry is worth knowing, but it is nowhere near a tradable directional push on its own. ## ④ What counts as normal, by timeframe 'Normal' has no absolute value here: wall build-up measured per second is a different quantity from the same thing aggregated over an hour or a day, and the scale grows by orders of magnitude (log axis). Every threshold we use later is therefore relative to its own window and its own coin — never a fixed number carried across timeframes. ## ⑤ Where the link peaks Each coin has a window where wall build-up lines up best with what follows, marked with a star. The peaks cluster at the short end — the information decays quickly, so any use of this signal has to act on the scale of seconds to minutes rather than hours. ## ⑥ Does the imbalance predict direction Barely. Taking the signed difference between the sell-wall build-up and the buy-wall build-up and correlating it with the direction of the next move gives at most ρ≈0.28 anywhere in the grid, and it collapses toward zero on most coins and most horizons. This mirrors what we found with volume: the book tells you how much, not which way. ## ⑦ How long one-sidedness survives A lopsided book does not stay lopsided. The share of imbalance that persists falls from about 73–79% at one second to roughly 7–10% by the twenty-minute mark. Whatever pushes wall build-up to one side is undone quickly — which is exactly why it cannot steer longer moves. ## ⑧ Memory: does a busy second predict a busy second Yes, and this is the most robust property in the whole study. Lag-1 autocorrelation of wall build-up is 0.33–0.50 at the fastest scale and 0.30–0.40 at the slowest, on every coin. The quantity is sticky: its own past is a better predictor of its near future than anything about price. ## ⑨ How extreme the extremes are Extremes are not mild. A peak second can carry many times the normal level of wall build-up, which is why averages describe this data badly and why we work with quantiles and episodes instead of means. ## ⑩ Where the seconds actually live Most seconds are unremarkable: the distribution of wall build-up is concentrated in the low bands with a long thin tail. The market spends the overwhelming majority of its time doing nothing interesting, and the tail is where every episode we care about comes from. ## ⑪ Spike, normal, lull — what each looks like We label every moment as spike, normal or lull relative to its own baseline, then look at how price behaves inside each state. The states differ from each other in volatility far more clearly than in direction — the same asymmetry that runs through the whole project. ## ⑫ The same states laid over price Here the labelling is placed directly on a price window so you can see it rather than trust it: where wall build-up flips state, and what price does around those flips. ## ⑬ Extremes arrive in clusters Spikes in wall build-up are not evenly spaced — they bunch into storms, and a spike inside a cluster is a different animal from an isolated one. Any threshold rule that ignores clustering will fire in bursts and then sit idle for hours. ## ⑭ What it forecasts, honestly Pulling it together: the two sides of wall build-up move together (coupling reaches 0.96–0.99 at the long end), the quantity forecasts its own future well, and it carries a positive signal about the *size* of the next move. What it does not carry — on any horizon we measured — is the side. That is the honest boundary of this study. _Research, not financial advice._ ================================================================================ # Liquidity Pulled: What Happens When a Wall Drains URL: https://marketflowresear.ch/articles/wall-drain-liquidity-pulled-before-the-move/ Published: 2026-07-31 · Series: Order-book research · Drain > We measured resting liquidity being pulled away from the book second by second across six coins, and asked the only question that matters: does it tell you anything about what happens next? It does — about size, not direction. ## ① Which side carries more of wall drain Across the whole archive the two sides sit close together: the ratio between the sell-wall drain and the buy-wall drain runs 0.94–1.05× depending on the coin. Neither side structurally dominates the book — which matters, because it means anything we find later is about *changes* in wall drain, not about a permanent imbalance between buyers and sellers. ## ② Does it predict the size of the next move This is the core question. Rank correlation with the size of the next move is **positive** on 6 of 6 coins, and strongest at the shortest horizon — +0.40 on BTC at 5s. By the daily scale it fades to +0.07. In plain terms: when wall drain runs high, the following window tends to be more volatile than usual, and the effect strengthens as the window widens. ## ③ How much price actually moves per unit We measure the price shift per +1σ of wall drain, split into low, middle and high bands. The effect is small in absolute terms — fractions of a basis point per σ — and asymmetric between the two sides. That asymmetry is worth knowing, but it is nowhere near a tradable directional push on its own. ## ④ What counts as normal, by timeframe 'Normal' has no absolute value here: wall drain measured per second is a different quantity from the same thing aggregated over an hour or a day, and the scale grows by orders of magnitude (log axis). Every threshold we use later is therefore relative to its own window and its own coin — never a fixed number carried across timeframes. ## ⑤ Where the link peaks Each coin has a window where wall drain lines up best with what follows, marked with a star. The peaks cluster at the short end — the information decays quickly, so any use of this signal has to act on the scale of seconds to minutes rather than hours. ## ⑥ Does the imbalance predict direction Barely. Taking the signed difference between the sell-wall drain and the buy-wall drain and correlating it with the direction of the next move gives at most ρ≈0.17 anywhere in the grid, and it collapses toward zero on most coins and most horizons. This mirrors what we found with volume: the book tells you how much, not which way. ## ⑦ How long one-sidedness survives A lopsided book does not stay lopsided. The share of imbalance that persists falls from about 65–77% at one second to roughly 9–12% by the twenty-minute mark. Whatever pushes wall drain to one side is undone quickly — which is exactly why it cannot steer longer moves. ## ⑧ Memory: does a busy second predict a busy second Yes, and this is the most robust property in the whole study. Lag-1 autocorrelation of wall drain is 0.35–0.51 at the fastest scale and 0.28–0.39 at the slowest, on every coin. The quantity is sticky: its own past is a better predictor of its near future than anything about price. ## ⑨ How extreme the extremes are Extremes are not mild. A peak second can carry many times the normal level of wall drain, which is why averages describe this data badly and why we work with quantiles and episodes instead of means. ## ⑩ Where the seconds actually live Most seconds are unremarkable: the distribution of wall drain is concentrated in the low bands with a long thin tail. The market spends the overwhelming majority of its time doing nothing interesting, and the tail is where every episode we care about comes from. ## ⑪ Spike, normal, lull — what each looks like We label every moment as spike, normal or lull relative to its own baseline, then look at how price behaves inside each state. The states differ from each other in volatility far more clearly than in direction — the same asymmetry that runs through the whole project. ## ⑫ The same states laid over price Here the labelling is placed directly on a price window so you can see it rather than trust it: where wall drain flips state, and what price does around those flips. ## ⑬ Extremes arrive in clusters Spikes in wall drain are not evenly spaced — they bunch into storms, and a spike inside a cluster is a different animal from an isolated one. Any threshold rule that ignores clustering will fire in bursts and then sit idle for hours. ## ⑭ What it forecasts, honestly Pulling it together: the two sides of wall drain move together (coupling reaches 0.94–0.98 at the long end), the quantity forecasts its own future well, and it carries a positive signal about the *size* of the next move. What it does not carry — on any horizon we measured — is the side. That is the honest boundary of this study. _Research, not financial advice._ ================================================================================ # The Wall That Goes Quiet: What Resting Liquidity Predicts URL: https://marketflowresear.ch/articles/resting-walls-what-thick-liquidity-predicts/ Published: 2026-07-31 · Series: Order-book research · Walls > We measured resting limit liquidity sitting on both sides of the book second by second across six coins, and asked the only question that matters: does it tell you anything about what happens next? It does — about size, not direction. ## ① Which side carries more of resting walls Across the whole archive the two sides sit close together: the ratio between the resting sell wall and the resting buy wall runs 0.93–1.06× depending on the coin. Neither side structurally dominates the book — which matters, because it means anything we find later is about *changes* in resting walls, not about a permanent imbalance between buyers and sellers. ## ② Does it predict the size of the next move This is the core question. Rank correlation with the size of the next move is **negative** on 4 of 6 coins, and strongest at the shortest horizon — -0.11 on BTC at 5s, with the remaining coins sitting near zero. By the daily scale it fades to -0.08. In plain terms: when resting walls runs high, the following window tends to be calmer than usual, and the effect weakens as the window widens. ## ③ How much price actually moves per unit We measure the price shift per +1σ of resting walls, split into low, middle and high bands. The effect is small in absolute terms — fractions of a basis point per σ — and asymmetric between the two sides. That asymmetry is worth knowing, but it is nowhere near a tradable directional push on its own. ## ④ What counts as normal, by timeframe 'Normal' has no absolute value here: resting walls measured per second is a different quantity from the same thing aggregated over an hour or a day, and the scale grows by orders of magnitude (log axis). Every threshold we use later is therefore relative to its own window and its own coin — never a fixed number carried across timeframes. ## ⑤ Where the link peaks Each coin has a window where resting walls lines up best with what follows, marked with a star. The peaks cluster at the short end — the information decays quickly, so any use of this signal has to act on the scale of seconds to minutes rather than hours. ## ⑥ Does the imbalance predict direction Barely. Taking the signed difference between the resting sell wall and the resting buy wall and correlating it with the direction of the next move gives at most ρ≈0.31 anywhere in the grid, and it collapses toward zero on most coins and most horizons. This mirrors what we found with volume: the book tells you how much, not which way. ## ⑦ How long one-sidedness survives A lopsided book does not stay lopsided. The share of imbalance that persists falls from about 42–59% at one second to roughly 6–10% by the twenty-minute mark. Whatever pushes resting walls to one side is undone quickly — which is exactly why it cannot steer longer moves. ## ⑧ Memory: does a busy second predict a busy second Yes, and this is the most robust property in the whole study. Lag-1 autocorrelation of resting walls is 0.74–0.83 at the fastest scale and 0.79–0.90 at the slowest, on every coin. The quantity is sticky: its own past is a better predictor of its near future than anything about price. ## ⑨ How extreme the extremes are Extremes are not mild. A peak second can carry many times the normal level of resting walls, which is why averages describe this data badly and why we work with quantiles and episodes instead of means. ## ⑩ Where the seconds actually live Most seconds are unremarkable: the distribution of resting walls is concentrated in the low bands with a long thin tail. The market spends the overwhelming majority of its time doing nothing interesting, and the tail is where every episode we care about comes from. ## ⑪ Spike, normal, lull — what each looks like We label every moment as spike, normal or lull relative to its own baseline, then look at how price behaves inside each state. The states differ from each other in volatility far more clearly than in direction — the same asymmetry that runs through the whole project. ## ⑫ The same states laid over price Here the labelling is placed directly on a price window so you can see it rather than trust it: where resting walls flips state, and what price does around those flips. ## ⑬ Extremes arrive in clusters Spikes in resting walls are not evenly spaced — they bunch into storms, and a spike inside a cluster is a different animal from an isolated one. Any threshold rule that ignores clustering will fire in bursts and then sit idle for hours. ## ⑭ What it forecasts, honestly Pulling it together: the two sides of resting walls move together (coupling reaches 0.85–0.98 at the long end), the quantity forecasts its own future well, and it carries a negative signal about the *size* of the next move. What it does not carry — on any horizon we measured — is the side. That is the honest boundary of this study. _Research, not financial advice._ ================================================================================ # About Market Research Lab — What We Collect and Why URL: https://marketflowresear.ch/articles/about-market-research-lab/ Published: 2026-07-29 · Series: Order-book research · About > Most market commentary is storytelling. We built something testable instead: 166 days of second-by-second order-book data across six coins, and a rule that nothing gets published unless it survives out-of-sample. ## ① What we collect Every second, around the clock, we record the Binance order book for six pairs — BTC, ETH, SOL, BNB, XRP and DOGE. For each pair we store eight microstructure features plus price: the resting buy and sell walls, how those walls thicken and thin out, and the raw buy/sell volume hitting them. The collector has been running non-stop since 14 February 2026; the archive is now 166 trading days and more than 11 million second-by-second rows per coin — roughly 60 million rows in total, growing every day. ## ② Why we do it Most crypto commentary is storytelling: a chart, a narrative, no way to check it. We wanted the opposite — claims small enough to be measured and specific enough to be wrong. Every statement we publish has a number behind it, a sample size, and a test on data the model never saw. If a claim can't survive that, it doesn't get published here. That includes our own favourite ideas: several of them died in testing, and we say so. ## ③ How we dig First we build baselines: what counts as 'normal' for this coin at this timeframe. Turnover per second is tiny; aggregate to minutes, hours and days and it grows by orders of magnitude, so a 'spike' only means anything relative to its own window — never as an absolute number. On top of those baselines we build feature profiles, a market-state oscillator, autocorrelation and event studies around unusual order-book behaviour. Predictions are written down first and scored later. No moving the goalposts. ## ④ What we test Three lines of work. Volatility forecasts built from order-book flow. A market-state oscillator that reads the tape's temperature. And trading bots — always walk-forward, always benchmarked against simple buy & hold, priced with a realistic 0.15% fee per action, with take-profit deliberately smaller than stop-loss. Live paper bots run a champion-versus-challenger tournament: a fresh candidate is trained after every closed trade and only replaces the incumbent if it actually scores better. ## ⑤ What we've learned: size is forecastable Order-book flow predicts how *big* the next move will be. Rank correlation runs around 0.55 in the moment and roughly 0.25–0.30 five minutes ahead — consistently, on all six coins. The cleanest validated pattern is the wall that drains: when resting liquidity is pulled without being replaced, the following window runs ×1.4–1.6 more volatile than usual, while a thick untouched wall precedes calm (×0.84–0.94). The edge is real but short-lived: strong in minutes, essentially gone by a day. ## ⑥ What we've learned: direction is not The same data says almost nothing about *which way*. Forward directional correlation is about zero by every method we tried — imbalance sweeps top out near ρ≈0.2 on BTC and ETH and collapse to zero on SOL, XRP and DOGE. Every purely directional strategy we tested lost out-of-sample: momentum, intraday, move-start detection, fade-the-turbulence. Gross edge came in below the round-trip fee, which is the honest way of saying there was no edge. So we forecast risk, not a guessed side. ## ⑦ Our promise The moment a strategy shows a positive, validated, out-of-sample result, it gets published here — the method, the numbers and the caveats, including the ones that hurt. Until then we keep digging in the open: each study becomes an article with its charts, and every chart is reproducible from the archive. Data collection, analysis, charts and narration are produced with AI assistance and reviewed by a human before anything goes out. ================================================================================ # Volume Is the Fuel — Not the Steering Wheel URL: https://marketflowresear.ch/articles/volume-is-fuel-not-steering-wheel/ Published: 2026-07-25 · Series: Order-book research · Volume > We recorded the Binance order book every second for six coins over five months and ran eighteen tests on what volume really does. The through-line: volume tells you how big the next move is — almost never which way. ## ① Buy vs sell — which side is bigger Over the full history, buying and selling are almost perfectly matched. Sell-volume is marginally larger on five of six coins — ratios from 1.02× (BTC) to 1.06× (XRP) — while SOL is fractionally buy-led (0.98×). Buy-share sits between 48.5% and 50.5%. No coin is structurally dominated by one side. ## ② Does volume predict the size of the move Yes — clearly. Flow intensity and the size of the next move rise together, strongest on the shortest horizons: rank correlation peaks around 0.22–0.33 within seconds and decays as the window widens. In event terms, an above-normal volume burst is followed by five minutes running ×1.4–1.7 more volatile than usual — on every coin. Volume is a size signal. ## ③ Who moves price more — buying or selling We measure the price shift per +1σ of volume. Aggressive buying nudges price up (about +0.10 bp/σ on BTC at the low band) while aggressive selling barely moves it (about −0.01 bp/σ) — a small, asymmetric impact ratio. Neither side gives a reliable directional push; buying just leaves a slightly clearer footprint than selling. ## ④ What counts as normal volume, by timeframe 'Normal' depends entirely on the clock. Per-second turnover is tiny; aggregate to minutes, hours and days and it grows by orders of magnitude (log scale). Establishing this baseline per coin per timeframe is what later lets us call a second 'a spike' — always relative to its own window, never an absolute number. ## ⑤ At which horizon volume predicts best The link is strongest almost immediately. Total flow's correlation with the move peaks at the ~5-second window (ρ≈0.33 on BTC) and fades monotonically toward the daily scale. Imbalance peaks much later (~10 min) and even there is tiny (ρ≈0.008). The usable edge is short-horizon, and it is about magnitude — not side. ## ⑥ Does imbalance predict direction Only weakly, and unevenly. Imbalance→direction correlation reaches ρ≈0.18 (BTC) and 0.20 (ETH) but collapses to about zero on SOL, XRP and DOGE. The directional bias is under ~1 bp per σ everywhere. So even the *side* of the flow — not just its size — is a poor compass for where price goes next. ## ⑦ How long imbalance lasts before it evens out Imbalance is fleeting. The share that persists falls fast as you widen the window — on BTC from ~84% at one second to ~40% at one minute and ~18% by twenty minutes. Buyers and sellers rebalance quickly; a one-sided burst rarely stays one-sided for long. That short lifetime is exactly why it can't steer longer moves. ## ⑧ Volume has memory (autocorrelation) Volume has real memory, and it grows with scale. Lag-1 autocorrelation of buy-flow on BTC rises from 0.23 (1s) to 0.36 (5s), 0.51 (1 min) and 0.57 (5 min). Busy seconds cluster into busy minutes — activity is self-reinforcing. This persistence is precisely what makes the size signal, volatility, forecastable at all. ## ⑨ Each coin's volume fingerprint Every coin has its own volume signature across timeframes — BTC and ETH trade in the thousands of coin-equivalents per bucket, XRP and DOGE in the hundreds-to-thousands — with buy and sell curves tracking each other tightly. These per-coin, per-window baselines feed every downstream test, so 'normal' always means normal for *that* market. ## ⑩ How big a spike really is A 'spike' is the top-1% second (above q99) for its coin and window. These peaks tower over the ordinary second — many multiples of the normal level — and they are exactly the moments the size signal fires. Defining them relative to each coin's own baseline keeps the comparison fair across very different markets. ## ⑪ Most seconds are quiet Sorting every second into 20 bands (ten below normal, ten above) shows a heavy concentration around and below the normal line, with a thin, long tail of high-volume seconds — the spikes. Buy and sell distributions mirror each other. The market spends most of its time idling, punctuated by rare bursts. ## ⑫ Episodes: spike / normal / lull Grouping seconds into episodes (spike >q80, normal, lull Across six coins, order-flow surges line up with bigger price moves — but not their direction. A walk-forward look at what the tape can and can't tell you. Volatility Order flow predicts how much, not which way Research note · 15 July 2026 · AI-assisted, human-reviewed Most market content is sold on direction : will it go up or down. We went looking for that signal in second-by-second order-book data across six major coins — BTC, ETH, SOL, BNB, XRP and DOGE — and kept running into the same result. Directional edge, tested out-of-sample, sits close to a coin flip. But a different quantity holds up well: how much the market is about to move. ≈ 0.5 Rank correlation between current order-flow intensity and the size of the next move — stable across all six coins, out-of-sample. Direction, by contrast, lands near zero. ## What we measured For each second we track eight order-book features: the resting walls on each side, how those walls grow or pull back, and executed buy/sell volume. From these we build a simple flow-intensity reading and ask a plain question: when flow spikes, what happens next? ## The pattern When walls thin out and flow surges, the following stretch tends to move harder — forward volatility rises meaningfully. When the book sits thick and quiet , the next stretch tends to stay calm. The link is to magnitude, not to a particular direction: an up-surge and a down-surge look almost the same on the way in. ## Why it matters It reframes what the tape is good for. Order flow is a decent volatility instrument — useful for sizing, timing and risk — and a poor compass . We publish results that survive walk-forward testing against a plain buy-and-hold benchmark, and we say clearly where the edge stops. ← All research