The Storm Class: Which Order-Book Feature Marks a Reversal
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.
Full walkthrough โ streamed from YouTube.
โ 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 โ the same question inside the calm class - Class 2 reversals โ the same question inside the class 2 class - Separating the signal โ all three classes side by side, everything we tried in between, and what this is worth for an automated system

If this changed how you read the tape, the natural next step is We Found the Reversal Signal. Machine Learning Could Not Tell It Apart. โ
We Found the Reversal Signal. Machine Learning Could Not Tell It Apart.
We Went Looking for the DNA of a Reversal. We Found a Ceiling Instead.
Volume Is the Fuel โ Not the Steering Wheel
We recorded the Binance order book every second for six coins over five months and ran eighteen tests on what volume really does.
About Market Research Lab โ What We Collect and Why
Most market commentary is storytelling.
Comments
Discussion is powered by GitHub. Enable it by adding secrets/giscus.json (repo IDs from giscus.app).