โ€บNavigation

Weekly Report ยท 21โ€“27 July 2026

Alpha research with bar-close features โ€” week of 21โ€“27 July

What I did this week, what it proved, and what I plan to do next โ€” across opendeviationbar-research, the new subordinator repo, and opendeviationbar-py.

Prepared for Terry Li by MD Nasim ยท Monday 27 July 2026
Scope: 21โ€“27 July only. Earlier work is deliberately excluded.
Written in first person, in plain English, with the evidence tables underneath each section.

The one-paragraph version

This week I built the strategy-killing engine and then used it to kill things. Between Tuesday and tonight the whole rejector went from nothing to a working P0โ†’P4 pipeline, and the first thing I pointed it at came back 616 trading rules tested, zero survivors โ€” the promoted bar-close features carry essentially no directional information at a 3-second horizon. On Saturday I built the cross-sectional machinery that I think is the most promising next direction โ€” running it is this week's work. Today I opened one new line of work (subordinators) and, separately, established that my own orthogonality probe fails its own control test and cannot currently certify anything.

Under our doctrine the deaths are the deliverable โ€” clean, adversarially-verified negatives that close off large search spaces cheaply. But I want to be direct with you: we do not have a tradeable edge to show, and nothing in this report should be read as one.

P0โ†’P4
rejector built, this week
616
rules backtested ยท 0 survivors
0/22
candidates passing the rotational probe
19/20
columns GROUNDED ยท 1 rejected
60
independent skeptic recomputations
1
new repo opened today

The week at a glance

DayWhat landed
Tue 21P0 gate โ€” causality-typed column contract, crypto/forex adapters, leakage guard T1โ€“T4, then an adversarial review of my own guards that found 12 issues, all fixed
Wed 22P0.5 โ†’ P3 in one day โ€” worst-fill crypto labels, Sharpe-free tail metrics + block-bootstrap CIs, exposure-matched drift null, FM-05 concentration falsifier, FM-13 cascade rejectors, DSPOT cascade dating, FM-12 OOD/LORO robustness
Fri 24The campaigns โ€” single-instrument pre-flight โ†’ DRY, the 5-symbol ร— 120-rule sieve (600 rules, 0 survivors), the BTCUSDT falsification loop, and the stop-and-ask ClickHouse rule added to CLAUDE.md
Sat 25Cross-sectional C1โ€“C3 machinery โ€” causal panel + dollar-neutral factor P&L (PR #29). Running it is this week's work โ€” ยง1.3.
Mon 27P4 validation (purge+embargo WFO, CSCV-PBO, e-BH, trial ledger), CI pipeline + /ci:* namespace, 8 correctness fixes to my own engine, PR #668 probe arbitration, and subordinator v1.0.0

What is in this report

ยงTopicWhere it stands
1opendeviationbar-research โ€” the engine, and what it provedMain negative โ€” 616 rules, 0 survivors, from a rejector built in five days
2Subordinators โ€” opened todayNew โ€” working measurement bench, no claim of edge, wants your go/no-go
3opendeviationbar-py โ€” probe, grounding, Axis-2Mixed โ€” one campaign complete at 19/1; the orthogonality probe found defective
4Validation machinery โ€” built vs actually runReported โ€” including which guards have never been exercised
5What I plan to do nextWhere your perspective would help
6How to check any number hereEvery figure traces to a committed artifact

1opendeviationbar-research โ€” the engine, and what it proved

In plain English

This is the repo I started after our call, and it is where almost all of this week went. Its job is not to find trading strategies. Its job is to kill them โ€” to take any proposed strategy and attack it with every known way a backtest can lie, so that anything surviving has actually earned it.

This week I built that attacker end to end, and then ran the promoted bar-close features through it. Nothing survived. Below is what I built, and then what it proved.

1.1 ยท What I built โ€” the rejector, P0 to P4, in five working days

The pipeline is a funnel of increasingly expensive tests. Cheap rejectors run first, so a bad strategy dies before I spend compute on it. Each gate targets a specific named failure mode from our FM catalog.

GateLandedWhat it doesGuards
P0 intakeTue 21 ยท #8 Causality-typed column contract + crypto/forex adapters โ€” every column is tagged with what it may legally depend on FM-01
P0 leakage guardTue 21 ยท #9, #11 T1โ€“T4 leakage tests. Then I ran an adversarial review against my own guards and it found 12 issues, all fixed FM-01
P0.5 labelsWed 22 ยท #20 Verify and adopt the crypto worst-fill labels โ€” every P&L is priced at the worst realistic fill from the first line FM-02
P1 metricsWed 22 ยท #21 Sharpe-free tail metrics (CVaR, CDaR, MaxTuW, Rachev, Omega) + block-bootstrap confidence intervals on real resampled data FM-07
P1 nullsWed 22 ยท #22, #23 Exposure-matched crypto-strata null โ€” the first-class drift/beta rejector โ€” plus the FM-05 concentration falsifier FM-03 ยท FM-05
P2 cascadeWed 22 ยท #24, #25 Cascade-conditional crash-premium rejectors, and DSPOT cascade dating with severity corroboration FM-13
P3 OODWed 22 ยท #26 Out-of-distribution robustness โ€” leave-one-regime-out plus covariate-shift detection FM-12
P4 validationMon 27 ยท #31 Purged + embargoed walk-forward, CSCV-PBO, e-BH multiplicity under arbitrary dependence, and an auto-tightening trial ledger FM-04 ยท FM-09 ยท FM-10
The sequencing is deliberate, and it is FM-08

FM-08 says don't build infrastructure the edge doesn't yet justify. Its operational form is cheap rejectors first. That is why P0/P0.5/P1 โ€” the gates that cost almost nothing to run โ€” landed before the expensive P4 deflation battery, and it is why the campaigns in ยง1.2 ran on Friday rather than waiting for the full stack. As it turned out, nothing got past the cheap gates, so the expensive machinery was never invoked. That is the funnel working, not a gap.

1.2 ยท What it proved โ€” 616 rules, zero survivors

With the gates in place I pointed them at the promoted bar-close features on Friday. Three separate campaigns, three independent methods, one conclusion. I am reporting them in order of how much they cover, not chronologically.

In plain English

I took every bar-close feature that had been promoted upstream, turned each one into simple trading rules โ€” "when this number is unusually high, buy; when it's unusually low, sell" โ€” and tested all of them on real crypto history. 616 rules. None of them made money. More importantly, they didn't fail narrowly. They failed by a factor of ten to a hundred, which tells us something much more useful than a near miss would have.

616
distinct rules backtested
0
survivors, all campaigns
5
crypto symbols, deep run
1.33
bps โ€” largest gross move found
4.65
bps โ€” cheapest possible cost
60
independent skeptic recomputations

Campaign C โ€” the main event: 5 symbols ร— 120 rules

For each symbol I enumerated a complete, operator-specified grammar: 15 promoted features ร— 4 quantile tails (p10/p25/p75/p90) ร— 2 directions = 120 rules. Signals are built from past-only rolling quantiles (rolling.quantile.shift(1)), so every rule is causal by construction. Each rule is priced at worst-fill, given a moving-block bootstrap confidence interval on real resampled data, then corrected for multiple testing with both Bonferroni and BH-FDR.

SymbolRulesTradeable bars Cost floor (bps)Largest gross move (bps) Best net CI-low (bps)Verdict
BTCUSDT120868,96916.900.31โˆ’18.73Dry
ETHUSDT1201,198,92815.07โˆ’0.52โˆ’17.62Dry
SOLUSDT1201,334,37415.490.00โˆ’18.15Dry
XRPUSDT1201,498,37418.26โˆ’0.39โˆ’25.98Dry
DOGEUSDT1202,596,40948.051.33โˆ’52.01Dry
Total6007,497,054โ€”โ€”โ€”0 survivors

Every one of the 600 rules carries verdict: "NO ALPHA" with death_reason: "no-directional-edge". Statistically: 0/600 significant under Bonferroni, 0/600 under BH-FDR, 0/600 with a positive confidence-interval lower bound. The outcome is completely homogeneous โ€” not one rule even reached the later cost-ceiling or multiplicity branches of the decision tree, because none of them got past the first gate.

Campaign A โ€” the BTCUSDT falsification loop

Earlier and deeper: a single feature (bar_petrosian_fd, the one producer-proven column) split into 5 quantile bins, each traded in its natural direction, each pushed through the full 8-gate failure-mode battery over 8.5 years of history.

RoundVariantTrades Mean net (bps)Profitable foldsVerdict
1LONG bin-0 (smoothest)209,229โˆ’21.190 / 5Falsified ยท FM-02
2LONG bin-1176,380โˆ’23.060 / 5Falsified ยท FM-02
3LONG bin-2149,906โˆ’29.880 / 5Falsified ยท FM-02
4SHORT bin-3145,238โˆ’48.540 / 5Falsified ยท FM-02/03/11
5SHORT bin-4 (choppiest)167,657โˆ’81.610 / 5Falsified ยท FM-02/03/11
โ€”Total848,410โ€”0 / 255 deaths, 0 survivors

The monotone pattern is itself informative: net P&L worsens strictly as bars get choppier (โˆ’21 โ†’ โˆ’23 โ†’ โˆ’30 โ†’ โˆ’49 โ†’ โˆ’82 bps), driven by the worst-fill cost floor rising from ~13 to ~57 bps. Choppier bars are more expensive to trade and no better directionally. There is no bin, and no direction, where the feature pays.

This campaign was attacked, and the attack changed the story

I ran 60 independent skeptic recomputations (12 failure modes ร— 5 rounds), each re-deriving the verdict from the raw parquet. 59 upheld, 1 refuted โ€” and the single refutation reinforced a death rather than overturning it. A separate attacker/defender pass on PR #7 conceded 6 challenges and forced real corrections: my original "real signal buried by cost" narrative was wrong. Once I stripped the worst-fill inflation and applied a block bootstrap that respects autocorrelation, the apparent directional tilt largely vanished. The honest reading became "no signal, plus cost" โ€” a stronger and less flattering conclusion than the one I started with. Not one core verdict was overturned, but the explanation was materially rewritten.

Campaign B โ€” pre-flight and the 21-symbol universe sweep

Before committing compute I ran a cheap sanity sweep: 11 baseline rules on BTCUSDT (momentum, reversion, order-flow imbalance, VWAP, plus an always-long control), then a read-only ClickHouse-side sweep across the entire liquid universe โ€” 21 USDT pairs ร— 4 thresholds (100/250/500/750 dbps). No rows were pulled; only medians were computed server-side.

Coarser thresholds do not rescue it. The threshold sizes the move that already happened by the time the bar closes; the forward move stays โ‰ˆ0 at every threshold while cost stays flat.

Why every rule died โ€” the one chart that matters

Best signal found
1.33 bps
Exchange fee only
4.65 bps
Real cost โ€” ETH
15.07 bps
Real cost โ€” BTC
16.90 bps
Real cost โ€” XRP
18.26 bps
Real cost โ€” DOGE
48.05 bps

Blue = the largest gross directional move any of 600 rules produced, before any cost is subtracted. Red = what it costs to trade, round-trip. Bars share one linear scale.

The distinction that matters: this is a signal problem, not a cost problem

If the features carried a real 20 bps edge that costs were eating, the answer would be engineering โ€” better fills, a cheaper venue, maker orders, negotiated fees. That would be solvable. That is not what I found. The best gross move across 600 rules is 1.33 bps and it sits on DOGE, the most expensive symbol in the set. On the four majors it is under 0.6 bps. Even if execution were completely free the edge would still be economically meaningless. At a 3-second horizon these features describe the bar that just closed; they do not predict the next one.

The mild upward tilt that lights up a naive screen (P(up) โ‰ˆ 0.5109) is market drift โ€” the fact that crypto went up over 8.5 years โ€” not feature skill. Compared against a drift-matched null instead of a coin flip, it strips to โ‰ˆ0.

What this rules out, and what it does not

Closed

Single-instrument, single-feature threshold rules on promoted bar-close features at 250 dbps / 3s, on the liquid crypto majors. This surface is exhausted. Widening it โ€” 2-feature combos, more symbols โ€” combines near-zero-information signals and mostly just inflates the multiple-testing tax.

Still open

Longer horizons than 3s. Cross-sectional / market-neutral construction (rank the universe, trade winners against losers โ€” this cancels the drift that dominated here). Multi-bar formations rather than single-bar features. Maker-side execution that earns the spread instead of paying it.

1.3 ยท The cross-sectional pivot โ€” machinery built Saturday, and what I'm working on this week In flight

In plain English

Every rule that died in ยง1.2 was a single-instrument rule: look at Bitcoin, decide about Bitcoin. The post-mortem showed the thing that beat them was not cost โ€” it was market-wide drift. Crypto went up over 8.5 years, that lifts everything, and it swamped whatever tiny signal the features carried.

The standard fix is to stop betting on the market and start betting on relative performance: rank the whole universe by a feature, buy the top, short the bottom, hold equal dollars on each side. Whatever the market does as a whole then cancels out.

The machinery landed Saturday โ€” PR #29, C1โ€“C3: a causal panel with an as-of join, and dollar-neutral factor P&L, reviewed and tested. That is the part that is done.

C4 โ€” the run against real data โ€” is this week's work, and it has not started. Pulling the panel needs a ClickHouse read, which under the stop-and-ask rule I added to CLAUDE.md on Friday (#19) means writing the mini-ADR first โ€” exact tables, columns, symbols, the precise read-only query, where it runs, and why the local slice cannot answer it. That is the next thing I do. So I am reporting this as in flight, not as a result: there are no cross-sectional verdicts yet and I have not pre-judged any.

Why this is the direction I have taken

It attacks the exact mechanism that killed everything in ยง1.2. Ranking the universe and trading winners against losers cancels the market-wide drift that defeated every single-instrument rule. It is the one hypothesis last week's negative result actively points toward rather than away from, which is why I built the machinery before anything else on the list.

1.4 ยท Monday night โ€” CI, and eight fixes to my own engine

A rejector with bugs in it is worse than no rejector, because it issues verdicts that look authoritative. So before doing anything else with it I spent Monday night attacking my own code. Eight correctness fixes landed, plus CI.

PRFixWhy it mattered
#32Normalise SHORT P&L by the entry fill, not the exit fillMade rounds 4โ€“5 ~1.7% optimistic. No verdict moved โ€” both were already catastrophically negative โ€” but the arithmetic was wrong.
#33Reject non-finite and non-binary labels in auc()A NaN or a non-binary label would previously produce a plausible-looking number instead of an error.
#34Test bins against the unconditional base up-rate, not a coin flipComparing to 0.5 makes market drift look like skill. This is FM-03 inside my own screen.
#35Fail closed when a selected symbol has no realisationSilent-NaN class of bug in the cross-sectional path โ€” exactly what this week's work will depend on.
#38Causal guard perturbs by permutation and resampling, not absolute noiseAbsolute-noise perturbation is defeated by quantised columns, so the FM-01 leak detector could pass a leaky feature.
#39First tests for panel.py + fail closed on unprovable FM-01 checksThe as-of join is the documented leakage risk in the panel and it had zero tests.
#40Replace synthetic-verdict tests with real known-verdict replaysHARD RULE 5 compliance โ€” no synthetic data, even in the test suite. The tests now replay real documented episodes.
#37Footnote rounds 4/5 as ~1.7% optimistic under the old formulaKeeps the published ledger honest about a number that has since been corrected.

CI landed as PR #36 โ€” a GitHub Actions pipeline plus a /ci:* slash-command namespace, per our cross-repo standard. #41 unblocked the ruff ratchet.

One caveat on CI I want to state plainly

The 112 MB data slice is gitignored and unavailable to runners, so CI runs a data-less subset only. The job is literally named tests (NO real data โ€” partial coverage) and prints "This job passing does not mean the engine is validated." The suite refuses to run data-less unless explicitly opted in, so a skipped suite can never silently read as green.

Current totals for the repo: 272 test functions across 19 files.

2The new topic I opened today โ€” subordinators New ยท 27 Jul

In plain English โ€” the whole idea in one paragraph

A subordinator is a different clock for chopping market data into candles. Instead of "a new candle every minute", you say "a new candle every 500 trades", or "every $1 million traded". That's it. The repo I opened today is a bench for measuring what that choice actually does to your data.

Why the clock is not a detail

Almost all market analysis starts by chopping the raw stream of trades into bars โ€” open, high, low, close, volume. By convention we chop by the wall clock: one bar per minute. But markets do not run at a constant speed. At 3am nothing happens. During a crash, thousands of trades land per second. So a 3am one-minute bar and a crash one-minute bar carry the same label and wildly different amounts of market.

You are measuring with a ruler whose markings stretch and shrink โ€” and then feeding those measurements to a model as if they were comparable rows in a table.

The fix is old: Mandelbrot & Taylor (1967) and Clark (1973) proposed you stop counting time and start counting activity. Close a bar every N trades, or every N dollars exchanged. Now every bar holds roughly the same amount of market. And the famous "fat tails" of returns โ€” the too-many-extreme-moves problem that breaks standard statistics โ€” largely go away. They were partly an artifact of using the wrong clock, not a property of the market. The mathematical name for re-indexing one process onto another process's clock is subordination (X(t) = Y(T(t))); T is the subordinator.

The insight the whole repo is built on

Every bar type that exists is just one choice of T. Time bars, tick bars, volume bars, dollar bars, imbalance bars, directional-change bars โ€” these are not seven different things. They are one thing with seven settings. Which means they can be put on a single bench and compared fairly, instead of argued about.

How the bench keeps the comparison honest

One design decision does all the work: a clock only ever answers one question โ€” where does each bar end? It never builds the bar. A single shared piece of code turns cut-points into candles, identically for every clock. Two clocks can therefore differ only in where they cut, never in what happens afterwards. Any difference you then observe is attributable to the clock and nothing else.

Adding a new bar type costs one method and one line in the registry, and it immediately inherits every test and every comparison. There are currently 12 clocks across 8 families.

Two traps it has already found

Trap 1 Some clocks manufacture the effect you'd claim to discover

Directional-change bars close on a price reversal, so consecutive bars alternate up-down-up by construction. Measured bar-to-bar correlation: โˆ’0.43 to โˆ’0.76 across days. Anyone who "discovers mean reversion" on those bars has discovered the ruler, not the market. A real finding has to beat that baseline first.

Trap 2 Some clocks are wildly unstable across conditions

The directional-change clock produced 9 bars on a quiet day and 54,412 on a crash day โ€” a 6,046ร— swing. A model trained on calm data sees a handful of rows per day; deployed into a crash it sees tens of thousands. That is not a shift in the features, it is a shift in the sampling process itself โ€” and no standard robustness check on features will catch it.

How this connects to our ODB work

ODB is a subordinator. It is a price clock: it cuts a new bar whenever price moves a fixed distance ฮด from that bar's opening price. So everything above applies directly to the bars underneath every number in this report.

Its nearest published relative is the directional-change clock, and the spec pins the exact difference: DC's reference point is a trailing extremum that keeps moving with the trend (so it confirms late), whereas ODB's is fixed at the bar's open for the bar's whole life (so it cuts every ฮด of displacement). That single difference is the entire distinction between the two families โ€” and until now it was an argument, not a measurement.

The bench has already killed one of my own ODB claims

An earlier comparison of mine said ODB was far more regime-stable than dollar bars โ€” 1.83 vs 7.76. Re-run with bar counts matched, it reversed: dollar bars were more stable, and my original result had been measuring threshold calibration, not clock design.

What did survive count-matching was different, and more interesting: ODB's tail truncation. Kurtosis 9.8 vs dollar bars' 98.5 on the worst day. So there is a real ODB property there โ€” just not the one I originally claimed.

And it has validated the abstraction against our production engine

A clean-room ODB clock written from the Rust source reproduced the production golden fixture bit-exactly: 45/45 bars matching on OHLC and timestamps, volume to 3e-13. That is the strongest evidence available that "cut-points plus one shared aggregator" loses nothing versus a real bar engine โ€” which is what makes the whole comparison bench trustworthy.

The honesty constraint โ€” the part I'd most like your view on

The repo explicitly refuses to claim any of this yields profit. It cites the one rigorous head-to-head study in the literature โ€” 60.5M EURUSD ticks, properly cross-validated, permutation-tested โ€” which found that ranking bar types by statistical niceness did not predict ranking by trading profitability. Every family landed at essentially coin-flip accuracy.

So the repo treats those as two separate claims and only measures the first, precisely. Success is defined as "measured it correctly", not "found an edge." Given that ยง1.2 of this report is 616 dead rules, I think that is the right posture for a measurement instrument โ€” but it is a deliberate constraint and you should know I chose it.

Where it actually is, stated honestly

v1.0.0
MIT ยท created 23:11 UTC today
76/76
invariant tests passing, 84s
12
clocks across 8 families
~950
lines of source
0
oracle-parity tests โ€” the big gap
none
CI

The test suite is the part I'd defend: six invariants ร— 12 clocks, plus targeted checks. The important one is C3 non-repainting โ€” re-run the clock on a truncated tape, and already-closed bars must be bit-identical. That is the FM-01 look-ahead guard expressed as an executable assertion. There is also a scale-invariance taxonomy test that multiplies all prices by k and asserts tick/volume/DC are unchanged while dollar must change โ€” the family taxonomy as a test rather than a comment. Per HARD RULE 5, no synthetic data anywhere: where a test needs a perturbation it uses a metamorphic transform of the real tape.

What is NOT there โ€” the repo's own list, not mine
  1. No oracle parity. Not one clock has been checked against an independent implementation. Self-consistent โ‰  correct, and the repo ranks this as its single biggest gap.
  2. The headline finding is about my implementation of a published recipe, not about anyone else's code. The repo refuses to phrase it as "the reference library is broken."
  3. Cross-clock comparisons are not yet legitimate โ€” thresholds were fixed, not cadence-matched. A count-matched campaign is the designated follow-up.
  4. ODB is not in the zoo yet, so both ODB findings above stay Tier B โ€” genuinely measured, but not currently reproducible, because they ran in a scratch directory I have since wiped. Adding the ODB clock is ~40 lines.
  5. One symbol only (BTCUSDT). No cross-symbol replication.
  6. No downstream task at all. Nothing here says anything about predictiveness โ€” and the repo's own cited evidence says the first does not imply the second.

Two PRs so far. #1 is merged: an ADR rejecting my own proposal to self-host ClickHouse on a 1TB USB drive โ€” killed on four independent grounds, including that exFAT cannot host a MergeTree at all for lack of hard links. Adopted instead: hot tier on internal SSD, cold tier as Parquet queried with DuckDB. #2 is open and substantive: the clock-zoo baseline across 6 regime-diverse days, with committed artifacts, SHA-pinned tapes, and tables auto-generated from the evidence so the prose cannot drift from the data.

My own read on it

This is a working, self-validated measurement instrument with one campaign in flight โ€” more than scaffolding, and clearly short of externally validated. It is hours old. I opened it because ยง1.2's result made me want to check an assumption that sits underneath everything we have tested: not "which feature predicts?" but "is the row the right row?"

I am not asking you to bless it as a workstream. I would rather you tell me whether that question is worth my time at all right now, or whether I should stay strictly on the crypto panel until it is exhausted. It is genuinely your call and I will drop it without argument.

3opendeviationbar-py โ€” this week

In plain English

ODB-py is the engine that makes the data โ€” it turns raw exchange trades into bars and computes the numbers that describe each one. My job there is quality control on the raw material: deciding which of those numbers are trustworthy enough to become permanent production columns.

Three things happened there this week. One campaign finished, one campaign started, and one piece of my own measurement apparatus was found defective. I'm leading with the defective one because it is the most important.

Scope note: ODB-py has been running since April, but everything below is 21โ€“27 July only. Earlier workstreams are deliberately out of scope for a weekly report.

3.1 ยท The rotational orthogonality probe โ€” 20 candidates, and the control test that broke it

In plain English

Before a new feature is allowed to become a permanent column, it has to prove it is telling us something we don't already know. That sounds obvious, but it's surprisingly hard: a new number can look novel on one slice of history and turn out to be a near-copy of an existing column once you look across different market conditions.

The rotational orthogonality probe is my attempt at a fair test. Instead of judging a candidate on one calendar window, it lays out a grid of market conditions โ€” asset, symbol, threshold, volatility low/medium/high, Asian vs US-EU session, up/flat/down trend โ€” keeps a ledger of how well each cell has been covered, and repeatedly attacks whichever condition is least tested until every reachable one has been hit twenty times. The idea is that a feature can't hide in a corner of the market I forgot to look at.

Mechanically it runs a five-stage cascade โ€” h_norm โ†’ sibling โ†’ ฯ โ†’ panel-Rยฒ โ†’ ฮพ โ€” and fuses the stages by worst-of, so a candidate is only as good as its weakest stage (BAN > WATCH > PENDING > PASS). It runs on 62/62 grounded crypto cells at 80,000 bars per cell, read-only against ClickHouse on bigblack. Its intended job was to set axis.orthogonal on the candidate registry โ€” that is, to be the promotion gate for the orthogonality axis, replacing the legacy |ฯ| + h_norm banlist.

The 20 candidates I have run through it

Two batches of ten, plus smoke iterations โ€” 22 full-cascade evaluations, and zero PASS verdicts. Every one of the 20 candidates still has axis.orthogonal deferred/null in the registry.

Batch-01 โ€” 10 candidates
CandidateWhat it measuresRotationalLegacy (fair)Died at
l_skewness_tau3L-moment skewness (ฯ„3)WatchWatchrho
l_cv_tau2L-moment coefficient of variation (ฯ„2)WatchWatchsibling
edge_spread_bpsEDGE effective-spread estimatorBanWatchsibling
roll_spreadRoll effective-spread estimatorBanPasssibling
corwin_schultzCorwinโ€“Schultz high/low spreadBanWatchsibling
abdi_ranaldoAbdiโ€“Ranaldo spread (degenerate, h_normโ‰ˆ0)BanBanhnorm
arcsine_occupationArcsine-law occupation timePendingPassโ€” (ฮพ fail-safe)
arcsine_argmaxArcsine-law argmax locationWatchPasspanel_r2 (0.7277)
longest_excursionLongest one-sided excursionWatchPasspanel_r2 (0.5514)
parkinsonParkinson range volatilityBanWatchsibling
Tally0 PASS ยท 4 WATCH ยท 5 BAN ยท 1 PENDING4 PASS ยท 5 WATCH ยท 1 BAN7/10 diverge
Batch-02 โ€” 10 candidates
CandidateWhat it measuresRotationalLegacy (fair)Died at
rogers_satchell_varDrift-independent OHLC volatilityBanBanhnorm
mann_kendall_zMannโ€“Kendall S trend statisticBanBansibling
psd_wiener_spectral_flatnessWiener entropy of the bar periodogramBanPasssibling (ฯ=0.9783)
psd_spectral_centroid_normfreqSpectral centroid of the periodogramBanPasssibling (ฯ=0.9783)
dhvg_indeg_outdeg_kldDirected-HVG irreversibility KLDPendingPassโ€” (ฮพ, 3/62 unstable)
guzik_increment_magnitude_asymmetryGuzik Poincarรฉ asymmetryBanBansibling (ฯ=0.9954)
porta_increment_sign_asymmetryPorta accel/decel asymmetryBanBansibling (ฯ=0.9954)
hvg_degree_assortativity_coefficientHVG degree assortativityWatchPasspanel_r2 (0.6327)
bowley_quantile_skewBowley quartile skewnessBanBanhnorm
moors_octile_kurtosisMoors octile kurtosisWatchPasspanel_r2 (0.6111)
Tally0 PASS ยท 2 WATCH ยท 7 BAN ยท 1 PENDING5 PASS ยท 0 WATCH ยท 5 BAN5/10 diverge

The test that broke the probe โ€” and why I ran it

Twenty candidates and zero passes is either a very demanding gate or a broken one. There is a standard way to tell the difference: run the probe on things you already know are good. So I took seven features the project already ships and already labels axis.orthogonal = PASS, and fed them back through the unmodified cascade as a negative control.

Result โ€” the probe failed its own control, 0 out of 7

Rotational: 0/7 PASS. Legacy: 7/7 PASS on the same values (6/7 when the real legacy probe is run on its own full 120-column panel). Every single rotational elimination happened at the same stage โ€” panel_r2 โ€” and unanimously. The mechanism is a mis-set threshold: a panel_r2 PASS requires r2_worst < 0.50, but the shipped features sit at 0.65โ€“0.91. The PASS path was effectively unreachable.

The saving grace, and the reason this is a calibration bug rather than a catastrophe: the verdicts came back WATCH, not BAN. The probe was not wrongly rejecting the shipped set โ€” it was unable to certify it. Max redundancy breadth across all seven was 0.0323 against a BAN dial requiring 0.80, so by its own breadth criterion none of them is broadly redundant.

I then ran the legacy probe on real data for the first time, and it has the opposite defect. Its panel carries 120 columns to the rotational probe's 112 โ€” the extra eight being open ยท high ยท low ยท close ยท vwap ยท lookback_vwap_raw ยท first_agg_trade_id ยท last_agg_trade_id. In other words, the legacy probe was ranking raw price levels and a monotone trade-ID counter as redundancy drivers: self_correlation_driven was true at 7/7, and 4 of 27 candidates had a price level or row counter as their worst driver.

The verdict โ€” PR #668, open now

Quoted from the PR body
Panel hygieneThreshold calibrationUsable as a gate?
RotationalCorrectPASS unreachableNo โ€” cannot certify
LegacyBrokenCan certifyNo โ€” certifies partly for wrong reasons

"Each probe holds exactly the half the other is missing. This is why the arbitration was never resolvable by running the two against each other, and it makes the repair small rather than a redesign."

The campaign verdict file states it plainly: "HALF-SETTLED. Both probes measured; both found defective; neither usable as-is." My decision on 27 July was repair both, don't pick a winner โ€” because each one is sound exactly where the other fails.

To what extent is it usable, honestly

AspectStatus
As a promotion gate (axis.orthogonal)Not usable as-is โ€” 0 PASS in 22 evaluations, and 0/7 on its own shipped controls. The pre-registration fixed the criterion in advance ("โ‰ฅ1 shipped feature PASS โ‡’ probe can certify; 0 PASS โ‡’ non-functional gate"), so this is that rule resolving, not a judgement call. The three-dial repair is frozen and the defect is calibration, not design.
Sibling stage (candidate-vs-candidate duplicates)Usable, genuinely additive โ€” legacy structurally cannot see this. It caught psd_wiener_flatness โ†” psd_spectral_centroid at ฯ=0.9783 and guzik โ†” porta at ฯ=0.9954. Legacy rated both members of the first pair PASS.
Sibling LOO-Rยฒ legSuspended from verdict authority โ€” a multivariate Rยฒ was being graded on a Spearman-scaled line. Blast radius: 1 verdict.
panel-Rยฒ bandMeasured mis-set โ€” applied to the 66 shipped columns it yields 5 PASS ยท 47 WATCH ยท 14 BAN, i.e. 92.4% non-PASS
ฮพ stageOver-quarantines โ€” returns PENDING on 10 of 20 candidates
three_axis_gate.pyStill wired to legacy โ€” and legacy is now known to rank trade IDs as redundancy. Must not be treated as authoritative until the hygiene fix lands.

What I am doing with them now

I froze a three-dial repair declaration before touching any code, so the fix can't be tuned to taste:

Where it actually stands tonight โ€” the repair is declared but NOT validated

The re-run that would prove the repair works (R2) aborted with Code: 241 MEMORY_LIMIT_EXCEEDED on DOGEUSDT@100. Diagnosing it turned up a real hole in my own resource discipline: the "5-core / 5 GB hard cap" I had declared capped only the Python client โ€” the ClickHouse server side was uncapped (max_memory_usage=0, max_threads=auto(32)). Over 741 probe fetches the server hit p50 1.61 GiB, p95 12.47 GiB, max 32.97 GiB, with 17 of 63 cells over 5 GiB. I have written that up as an amendment rather than quietly re-running with a bigger budget.

So: two candidates are carried forward โ€” dhvg_indeg_outdeg_kld (panel-Rยฒ 0.4752) and arcsine_occupation (0.1671), the only 2 of 20 that cleared every substantive stage and were held back solely by the ฮพ fail-safe โ€” and nothing gets promoted on this axis until R2 completes.

Two catches I'd keep even if the probe is scrapped

Self-correlation confound. A first BTCUSDT@250 spot check showed only 0.69 and nearly let a duplicate through. Worst-cell driver attribution โ€” asking not just "how redundant?" but "redundant with what?" โ€” is what caught it.

Silent kernel death. 5 of 27 kernels returned all-NaN because only numpy/pandas/scipy were installed. They failed as PENDING โ€” indistinguishable from a genuine fail-safe. A silent failure that looks exactly like a legitimate verdict is the worst category there is, and this one was in my own research code. A 27/27 finite-value preflight is now mandatory before any cascade runs.

3.2 ยท Instrument grounding โ€” the campaign that finished Complete

In plain English

Section 3.1 asks "is this feature new?" This campaign asks the harder question: "is what this feature claims to measure actually real, and is it useful?" A number can be perfectly novel and still measure nothing. This ran every promoted column up a grounding ladder (F0โ€“F4) until each one reached a terminal verdict.

It ran across the week โ€” the laptop-drives-bigblack loop harness on Wednesday (#655), a SEAL-PASS cycle the same day (#657), cycle 2 on Thursday (#658), and closure on Friday (#661).

20/20 terminal โ€” campaign complete

19 GROUNDED ยท 1 REJECTED ยท 0 PARKED, plus 11 discovered and 0 left under evaluation. This is the only major campaign in this report that reached a terminal state on every single item.

The rejection (#12) is the load-bearing part. A grounding ladder that grounds everything is a rubber stamp. One column went in with the same standing as the other 19 and did not come out โ€” which is the only evidence I have that the other 19 verdicts mean anything.

3.3 ยท The evaluation framework โ€” what we are building and why

The goal, stated plainly

We are trying to find features that let us build two specific kinds of strategy: strategies that stay robust out of distribution โ€” that keep working when the market stops looking like the data they were fitted on โ€” and strategies that are liquid and cascade-free, meaning we can actually get in and out without being caught when liquidity evaporates.

That goal is why the framework exists. It is not a generic feature-scoring tool; it is built backwards from those two properties.

It reconciles three strands of work that had been running separately โ€” the forward-predictiveness measurement stack, the realness/usefulness instruments, and the new cascade-free candidate harvest โ€” into a single funnel with two named axes:

Axis 1 ยท OOD-robust Grounded

Regime-invariance. A feature counts as orthogonal only if it stays non-redundant and keeps its meaning across market climates โ€” tested with causal-invariance methods rather than a correlation score. This is what "out-of-distribution robust" reduces to at the feature level.

Axis 2 ยท Cascade-free Frozen, evaluation next

Liquidity and crowding. How liquid and un-crowded a position is โ€” orthogonal to price by construction. This is what "liquid, cascade-free" reduces to at the feature level.

The trap the framework is built to avoid โ€” this is the part I'd point at

The 19 grounded instruments from ยง3.2 all ask one question: "does this predict forward return?" Axis-2 candidates are orthogonal to price by construction. So pointing those instruments at these 120 candidates would score every one of them at roughly zero and reject the entire cohort โ€” and it would look like a clean, rigorous result.

The fix is to swap the target. A liquidity metric is judged on whether it predicts what it costs to trade, and above all on whether it warns before costs blow up โ€” against the cost-realism labels from ยง3.4, which already record exactly that. So it is an existing yardstick, not one invented for the occasion.

What we have done so far

How we plan to run it

Cheapest filters first, so the most candidates die for the least compute. Default is EXCLUDE โ€” a candidate advances only by clearing a gate. One gate per loop firing.

GateAsksKind
SEALDo the controls themselves work? A C1โ€“C4 self-test, before any real candidate is touchedself-test
F0Computable at all โ€” spot-legal, no order-book requirement, a Python path existsdeterministic
F1Non-degenerate and dense enoughinferential
F2Not a duplicate โ€” against the shipped set and within the cohortinferential
F3Beats the raw-volume baseline โ† expected to do most of the killinginferential
F4Real and useful against the cost targets โ€” multiplicity-corrected, power-backedinferential
F5Holds across market regimes โ€” the ship barinferential

Frozen thresholds: F2 BAN at max|ฯ| > 0.95 ยท F3 retention R โ‰ฅ 0.5 ยท F4 null FPR โ‰ค 0.05, BY-FDR at q = 0.10, PBO โ‰ค 0.2, power โ‰ฅ 0.80 ยท F5 k-of-N binomial exceedance at ฮฑ = 0.05.

Current state, stated exactly

120 in the frozen cohort ยท 0 decided ยท 0 admitted ยท SEAL gate due next. Nothing has been evaluated yet, and that is deliberate rather than incomplete โ€” the rulebook was frozen first precisely so the anticipated failure above could not be dressed up as a finding. Evaluation begins from the SEAL self-test.

For calibration: the comparable Axis-1 campaign ended 16 admitted against 45 killed, and the pre-registration expects roughly 19 of the 120 to park for want of order-book data this system does not carry.

The page that describes how we evaluate features

The methodology above is published as a live page โ€” the question, the trap, the funnel, the rules that cannot be bent, and an append-only ledger that fills in as gates fire:

findings/dashboard/probes/2026-07-24-axis2-cascade-free-evaluation/index.html
  โ†’ odb.epatner.com/opendeviationbar-py/dashboard/probes/2026-07-24-axis2-cascade-free-evaluation/

The narrative overview that sets up both axes in plain English, if you want the thesis before the mechanics, is probes/regime-invariant-orthogonality-campaign-2026-07-22.html ("Orthogonality Direction โ€” Design Preview").

One housekeeping note: neither page is currently linked from the dashboard hub, site-map, or probes index, so they are reachable only by direct URL. My own check-orphan-pages.py is what should have caught that, and I am regenerating the nav.

Where your perspective would be useful

This framework is a bet on what matters. I have aimed it at out-of-distribution robustness and liquidity/cascade-freedom because those are the two properties I think a strategy needs to survive contact with a real market โ€” and everything downstream inherits that choice. If you read the axes differently, or would weight them differently, the time to say so is now, while nothing has been evaluated and the cohort is still frozen.

3.4 ยท Cost-realism label backfill โ€” hardening

The label_fwd_3s_* family is what makes the honest-cost numbers in ยง1.2 possible. The kernel itself landed earlier in July; this week was the hardening pass after the first real production run.

PRWhat it fixed
#627Written audit of the BTC label backfill โ€” execution, incidents, and robustness follow-ups. The record of what actually happened, not what was supposed to.
#631Real-ClickHouse test harness + anti-join integration tests โ€” the resume logic is now tested against a real database, not a mock.
#635Memory backpressure โ€” bounds the parallel backfiller's RSS so it can't take the box down.
#648Order-independent sequential resume via anti-join and a retire watermark โ€” a restart no longer depends on the order work completed in.
#649Operator runbook โ€” step-by-step safe procedure for a human driving the backfiller.
#650Rebuild-coupling: orphan-label preflight, so a rebuild can't leave labels pointing at bars that no longer exist.
#647Substrate-validity gate โ€” closed the ฮพ substrate caveat by validating the result on the actual substrate rather than a proxy.
One bug from this week worth your attention

#660 (closed Thursday): a test fixture bar was leaking into the production open_deviation_bars table via the Rust sink path, because the guard against it was Python-only. Test data reaching a production table is the exact class of silent corruption that is invisible until someone trusts the numbers. Worth checking whether any other guard in the system is similarly implemented on one side of the language boundary only.

3.5 ยท Where candidate coverage actually stands

Context for ยง3.1 and ยง3.2, because "110 candidates in the registry" reads far more complete than it is:

110
candidates in the registry
32
touched by any evaluation
78
never evaluated
12
PASS on axis.orthogonal
66
still need a kernel written
13
runnable right now

By orthogonality verdict: 88 null ยท 12 PASS ยท 5 BAN ยท 4 WATCH ยท 1 PENDING. Of the 88 unresolved, 13 are runnable today, 9 need only a reuse-confirmation, and 66 need a kernel implemented before they can even be tested. After batch-02 there were 3 runnable candidates left in the queue. The machinery is considerably further along than the coverage โ€” and per ยง3.1, the gate that would resolve the rest is currently the thing that's broken.

4Validation machinery โ€” built vs actually run

I want to be precise here, because "we built a CSCV-PBO module" and "we have a PBO number" are very different claims and it would be easy to blur them.

ComponentGuards againstStatus
Worst-fill honest-cost P&LFM-02 optimistic costsRun ยท committed
Causal quantile binning / Phase-1 screenFM-01 look-aheadRun ยท committed
Moving-block bootstrap CIs (real-data resampling)autocorrelation false alarmsRun ยท committed
Bonferroni + BH-FDRFM-09 multiple testingRun ยท committed
Exposure-matched random-entry nullFM-03 drift-as-alphaRun ยท committed
Purged/embargoed walk-forward foldsFM-04 overfit / winner's curseRun ยท committed
Permutation nullFM-05 concentrationRun ยท committed
Cascade-dependence checkFM-12/13 crash-premiumRun ยท committed
CSCV-PBO (252 splits, MaxTuW-scored)FM-04/09 backtest overfittingBuilt ยท never run
e-BH multiplicity (Wang & Ramdas 2022)FDR under arbitrary dependenceBuilt ยท never run
Trial ledger (auto-tightening denominator)FM-09/10 hidden search costBuilt ยท never run
OOD / LORO + covariate shiftFM-12 regime fragilityBuilt ยท never run
Cascade DSPOT dating + LOCOFM-13 liquidity-cascade premiumBuilt ยท never run
Tail metrics (CVaR, CDaR, MaxTuW, Rachev, Omega)FM-07 Sharpe worshipBuilt ยท never run
Cross-sectional panel + factor P&Lthe drift problemExecution gated
P5 trade-by-trade reconciliation oracleimplementation errorPlanned only
P6 discovery engine (GP / PySR)โ€”Not built yet
Why half the battery has never run โ€” and why that's deliberate

FM-08 says don't build infrastructure the edge doesn't yet justify, and its operational form is cheap rejectors first. The heavy deflation battery โ€” CSCV-PBO, e-BH, OOD/LORO โ€” is reserved for rules that clear the cheap cost gate. Zero rules cleared it, so the expensive machinery was never invoked. That is the funnel working as designed, not a gap.

The honest flip side: there is no computed PBO, DSR, or Sharpe value anywhere in the research repo. The first is because CSCV-PBO has only ever been exercised in unit tests; the latter two are banned outright by FM-07. If you ask me for a Sharpe ratio I do not have one, by policy.

Reference โ€” the failure-mode catalog

Every verdict in this report cites one of these. The catalog started at 10 codes, now stands at 13, and grows toward the 29-bucket canonical inventory in the patterns repo. Worth noting that FM-13 was minted and then withdrawn during the PR-#7 adversarial pass โ€” its diagnostic turned out to be a worst-fill artifact โ€” and later re-grounded on Brunnermeierโ€“Pedersen (2009). The catalog gets falsified too.

CodeNameOne line
FM-01Look-ahead / feature leakA feature or label-scaling window using information not available at the decision instant
FM-02Optimistic (mid-price) costsPricing fills at mid instead of worst-fill โ€” manufactures edge โ‰ˆ the round-trip spread
FM-03Drift mistaken for alphaConfusing the market's own directional drift with strategy skill
FM-04Overfitting / winner's curseEdges that exist only because the window was short or the candidate was best-of-many
FM-05P&L concentrationTotal profit carried by one year, one fold, or a handful of trades
FM-06Tautological / redundant rulesAlways-true rules that inflate survivor counts and corrupt the multiple-testing denominator
FM-07Sharpe / smooth-metric worshipRanking by Sharpe on non-Normal, non-IID event-bar returns โ€” rewards artifact smoothness
FM-08Infrastructure before edgeBuilding throughput before an edge is validated โ€” zero added capability, multiplied mistakes
FM-09Uncorrected multiple testingSignificance without accounting for N hypotheses โ€” applies on the break side too
FM-10Overfitting to the batteryThe failure mode of the method itself โ€” a fixed N tests becomes a fitting signal
FM-11Sub-cost directional ceilingAn ODB bar closes on a fixed ยฑthreshold, so mean per-bar move is pinned by the threshold
FM-12Distribution-shift fragilityResampling controls selection overfitting under one regime, not regime change
FM-13Liquidity-cascade premiumImplicitly-short-vol strategies look like clean alpha in-distribution, then blow up

Source of truth: research-audit/failure-modes/README.md (not the top-level README, which only links to it).

5What I plan to do next

5.1 ยท Other work in flight

Besides the cross-sectional run in ยง1.3, which is the main one:

RepoOpenStatus
opendeviationbar-py#668 โ€” probe arbitration, negative control + real-legacy head-to-headOpen โ€” repair frozen, R2 validation aborted on a memory limit
opendeviationbar-pyAxis-2 evaluation โ€” 120 frozen candidates, SEAL gate due nextOpen โ€” ยง3.3, evaluation begins from the self-test
subordinator#2 โ€” clock-zoo baseline across 6 regime daysOpen โ€” full provenance + telemetry artifacts

The eight correctness PRs on the research repo (#32โ€“#41) all landed Monday night, so that queue is clear.

5.2 ยท The order I intend to take them in

  1. Write the data-access mini-ADR and run the cross-sectional sieve. The machinery from ยง1.3 is finished and tested; the ADR is what stands between it and real data. This is the main line because it attacks the exact mechanism that killed all 616 rules.
  2. Close the provenance gap. The five slices behind the 600-rule result have no data/PROVENANCE.md entry and live on bigblack rather than in the repo, and the BTCUSDT 15-feature slice has no SHA256 recorded anywhere. Backfilling it is cheap, and until it is done the result is documented but not reproducible from repo contents.
  3. Fire the SEAL gate on the Axis-2 cohort. 120 candidates are frozen and the rulebook is fixed. The self-test comes before any real candidate, so that is the next firing.
  4. Get R2 to complete on the probe repair. The three dials are frozen but the validating re-run died on a ClickHouse memory limit, and the resource envelope needs fixing properly โ€” the server side was never actually capped. Until R2 lands, axis.orthogonal cannot be set and 78 unevaluated candidates stay where they are.
  5. Hold the subordinator work at its current size. It is days old and I am not letting it grow until it has been weighed against the crypto panel.

5.3 ยท Where your perspective would be useful

Nothing here is waiting on a decision from you โ€” the list above proceeds either way. But there are three places where your read would genuinely change what I do, and this is the natural point to raise them.

On the direction of the alpha research

Single-instrument, single-feature rules at a 3-second horizon are now closed off on crypto. The two live continuations are cross-sectional โ€” market-neutral at the same horizon, which cancels the drift that beat everything โ€” and longer-horizon, same construction at 30sโ€“5min, which grows the signal against a roughly fixed cost. Both are scoped and ready. I have taken cross-sectional first because the post-mortem points there, but I hold that view loosely and I do not think it is worth widening the current surface any further in either case.

On the open work

The framework in ยง3.3 is a bet on what matters โ€” out-of-distribution robustness and liquidity cascade-freedom โ€” and everything downstream of it inherits that choice. The cohort is frozen and nothing has been evaluated, so this is the cheapest moment it will ever be to re-aim it. The same applies to the subordinator work in ยง2, which I am deliberately keeping small until it earns more.

On the report itself

This is the first weekly cut in this shape. If the balance is wrong โ€” too much method and not enough result, or the reverse โ€” it is easy to change, and I would rather adjust the format now than keep sending something that is not what you want to read.

6How to verify any number in this report

Every figure here traces to a committed artifact. The primary sources, in order of authority:

ClaimSource of truth
600 rules, 5 symbols, 0 survivorsresearch-audit/loop-runs/enumerate-sieve-*-250-15feat.json (primary) ยท research-audit/findings/2026-07-24-single-instrument-crypto-dry.md
5-round BTCUSDT loopresearch-audit/loop-runs/round-{1..5}-*-report.json ยท findings/loop-ledger.md
Skeptic recomputationsresearch-audit/loop-runs/skeptics/ ยท round-{1..5}-skeptics.json
Attacker/defender concessionsresearch-audit/loop-runs/pr7-attacker.md ยท pr7-defender.md ยท round-*-adversarial-corrections.json
11-rule pre-flightresearch-audit/loop-runs/preflight-2026-07-22-btcusdt-250dbps.json
21-symbol universe sweepscripts/preflight_ch_sweep.sh (exact read-only SQL) ยท audit spoke 02
Cost modelsrc/odb_research/{costs,labeling,labels}.py ยท data/PROVENANCE.md
Failure-mode definitionsresearch-audit/failure-modes/FM-{01..13}-*.md

Reproducer for the main campaign, per symbol

uv run python scripts/enumerate_sieve.py --all-features \
  --data data/<SYMBOL>_250dbps_15feat.parquet \
  --out research-audit/loop-runs/enumerate-sieve-<SYMBOL>-250-15feat.json \
  --table research-audit/loop-runs/enumerate-sieve-<SYMBOL>-250-15feat.md

Runs on bigblack under a 5-core / 5 GB hard cap (systemd-run --user --scope -p CPUQuota=500% -p MemoryMax=5G -p MemorySwapMax=0); peak RSS โ‰ˆ 1 GB, 3โ€“6 min per symbol. Note the provenance gap flagged in ยง5 โ€” the input slices live on bigblack, not in this repo.

Report scope

Read-only reconciliation across four repositories. No code, data, or artifact was modified to produce this document. All results are the repos' own committed outputs; I did not re-execute the test suite, any SQL, or any reproduce script for this report.

Doctrine reminder. Verdicts here are falsified or survived this round โ€” never pass, fail, or go. Nothing in this report constitutes a claim of tradeable edge. Default verdict for every strategy remains NO ALPHA.