Alpha-Investing — Sequential FDR Control
What goes wrong with a naive approach
The runtime maintains dozens of simultaneous monitors: conformal frame-guard alerts, allocation-budget CUSUMs, flake detectors, BOCPD regime flips, fairness interventions. Each one tests at some significance level . If they all test at independently and you have 20 monitors, the expected number of false positives per frame is . Multiply by 60 fps and you are drowning.
The usual answers are all bad:
- Bonferroni correction — divide by the number of tests. Works for fixed- testing but is catastrophically conservative when tests run continuously and new ones come online at runtime.
- Manual prioritisation — pick three “important” alerts, mute the rest. Fragile: the muted alerts are exactly where the next outage will come from.
- Unthrottled — accept the noise. Users stop trusting the alert system, which is worse than not having one.
The right abstraction is sequential false-discovery-rate control: a global budget that is spent when you reject (fire an alert) and recovered when rejections are themselves rejected in their own local tests.
Mental model
Think of it as a gambling game:
- You start with wealth (an budget).
- To run a test at level , you spend from your wealth.
- If the test rejects (alert fires), you earn back a reward — you were “right” to spend on it.
- If the test accepts, the is lost.
As long as the wealth stays non-negative and you stay within the rules, the marginal false discovery rate (mFDR) is bounded:
where is the number of false rejections and the total rejections.
The beauty of alpha-investing is that it respects the alert authors. Each subsystem still owns its test and picks its own . The wealth process enforces a global budget without imposing global coordination.
The math
Wealth update
For test with level :
where is the rejection indicator and is the reward fraction.
Admissibility
A test at level is admissible iff:
where is the investment fraction. This is the “don’t bet the farm” rule — you can’t spend your entire wealth on one test.
mFDR guarantee
If and , then:
for any stopping rule, any test order, any number of tests — the guarantee is sequential.
Defaults
| Parameter | Default | Meaning |
|---|---|---|
| 0.5 | Starting budget. | |
| (reward fraction) | 0.5 | Earnings per rejection. |
| (investment fraction) | 0.1 | Max fraction of current wealth per test. |
With these, and so the guarantee holds with .
Why you need it when running dozens of monitors
20 independent monitors @ 0.05
E[false alerts per frame] = 20 × 0.05 = 1.0
E[false alerts per second at 60 fps] = 60
→ alert log is 99% noise.
→ users ignore alerts, outages slip through.Rust interface
use ftui_runtime::alpha_investing::{AlphaInvestor, InvestmentConfig};
let mut investor = AlphaInvestor::new(InvestmentConfig {
initial_wealth: 0.5,
reward_fraction: 0.5,
investment_fraction: 0.1,
});
// Subsystem proposes a test at level 0.03
if let Some(ticket) = investor.request(0.03) {
let rejected = run_local_test();
investor.resolve(ticket, rejected);
} else {
// Not enough wealth — defer or pick a cheaper test.
}Every subsystem that wants to raise an alert first asks the investor for a ticket. If the wealth can’t support the , the test is suppressed for this frame — the budget speaks.
How to debug
Each admissible test emits an alpha_invest line:
{"schema":"alpha_invest","test_id":"budget_alert",
"alpha_i":0.03,"wealth_before":0.48,
"rejected":true,"wealth_after":0.465,
"reward":0.015}FTUI_EVIDENCE_SINK=/tmp/ftui.jsonl cargo run -p ftui-demo-showcase
# Which monitors are bleeding wealth?
jq -c 'select(.schema=="alpha_invest" and .rejected==false)
| .test_id' /tmp/ftui.jsonl | sort | uniq -c | sort -rnIf wealth trends to zero and stays there, the system is chronically “unhealthy” — the monitors are firing real alerts. Investigate the subsystem with the highest rejection rate first.
Pitfalls
Wealth can pin at zero. Once wealth is depleted, new tests are rejected without running. That is the correct FDR behaviour, but it means you lose visibility during outages when you most want it. Pair with a watchdog that emits a single “wealth exhausted” event at the sink level so you notice.
Rewards must correspond to real signal. If a subsystem games the wealth by rejecting under trivial conditions, its rewards accumulate and subsequent tests become effectively unbounded. Code review the test implementations; the mFDR guarantee assumes they are honest.
Cross-references
- E-processes — per-test anytime-valid machinery that feeds into the investor.
- Conformal frame gating — a major consumer of alpha-investing wealth.
/runtime/evidence-sink— howalpha_investlines are emitted.