Equity Control
Every strategy eventually asks the same question: is this drawdown normal, or is the edge gone? Equity Control answers it with two tools: a health diagnosis (is the recent path inside the strategy's historical physiology?) and an overlay simulation (what would a disciplined On · Reduce · Off governance have cost or saved?).
You can run it on the whole portfolio or a single strategy. Active weekday filters are respected, and — like Monte Carlo — the series is built from operating days only (days with non-zero P/L). All windows, cooldowns and lags are counted in operating days, so a slow strategy is not penalised by calendar time.
Analysis, not signals
Equity Control is a diagnostic instrument. Its states are advisory readings on your data, not trading orders: VECTOR does not connect to a broker and does not execute anything. Whether to act on a Stopped reading is — and remains — your decision.
Baseline and monitoring window
The series is split in two:
- Baseline — everything except the tail. This is the strategy's "physiology": thresholds are calibrated on it and never see the monitored data.
- Monitoring window — the last N operating days under diagnosis, defined by the split you set (see below). There is no silent auto-split: you choose where the In-Sample ends.
At least 60 baseline days and 10 monitoring days are required. Reliability tiers: with 300+ baseline days thresholds are fully estimable; 150–299 days are indicative (tail thresholds carry wide uncertainty); below 150 the diagnosis should be read as descriptive only. A warning is shown for each tier below full.
Setting the split by date. The primary control is In-Sample end: the In-Sample (calibration) runs up to that date, and everything after it is the monitored live window. It takes precedence over the numeric live-tail length (kept under Advanced for those who prefer counting operating days). One of the two must be set — until you define the split there is no diagnosis (no auto-default is applied, so opening the panel does not pre-judge an In-Sample you did not choose). Where you put this boundary is a first-order decision — the same strategy on the same data can read healthy or stopped depending on whether a regime shift falls inside the calibration or inside the monitored window. Choose the In-Sample to match the backtest you actually validated.
After a successful run the parameter form folds into a one-line recipe strip (source · split · governance · α) so the page opens on the verdict; Edit parameters reopens the full form, and Collapse parameters folds it back without re-running.
Bounding the range by date. By default the whole history is analysed. Two optional calendar fields under Advanced restrict it: Monitor from drops baseline older than that date, and To (as-of) ends the analysis on a past date — the diagnosis then runs as if that day were today, which is how you replay the governance at an earlier point. The live tail is always the final stretch of the bounded range. The Align with session button (next to those fields) fills both with the current session's data span (the union of the visible strategies' dates, or the selected strategy's own range).
In-Sample sufficiency (the gate)
Before anything else, the module checks that the In-Sample is large enough to validate the edge — you cannot meaningfully monitor the decay of an edge you have not first established. The check follows Bailey and López de Prado (2012) and combines two hard floors with a power criterion:
- Floors — at least 60 operating days and, when the trade count is known, 30 trades in the In-Sample. Below either, the diagnosis is blocked.
- Probabilistic Sharpe Ratio (PSR) — the probability that the true Sharpe is positive, given the observed Sharpe corrected for skewness and kurtosis. Fat tails and negative skew lower it.
- Minimum Track Record Length (MinTRL) — the minimum number of operating days needed for PSR to reach
the required confidence (95%). It grows as
1 / Sharpe²: a weak edge needs a much longer track record to be told apart from zero.
The gate passes when the floors are met and PSR ≥ 95% (equivalently, In-Sample days ≥ MinTRL). The Sharpe used is per-observation (MinTRL is in operating days); the panel also shows the annualised figure.
Hard block on insufficient data
If the In-Sample cannot validate the edge, the diagnosis is blocked — the module does not produce a verdict. The pre-flight semaphore under the form shows the outcome live as you move the In-Sample end date: green (edge validated, Run enabled — a quiet one-line confirmation with PSR and MinTRL, full detail in its tooltip) or red with the shortfall (e.g. "you have 285 days, you need ~801 — extend the In-Sample"). A non-positive In-Sample edge (mean P/L ≤ 0) is also blocked: there is no advantage to validate.
The method, exactly
1. Deflated healthy hypothesis
Thresholds are not calibrated on the raw baseline edge. A healthy strategy typically earns less
live than in its backtest (selection and overfitting haircuts), so calibrating on the raw mean would
flag perfectly healthy strategies. The "healthy" hypothesis H0 is the baseline series with its mean
shrunk to (1 − haircut) · μ (default haircut 25%), preserving volatility, skew and clustering.
Scenario paths are generated with the stationary bootstrap (Politis-Romano) using the
Politis-White automatic block length — the same implementation as the Monte Carlo module.
If the baseline mean is ≤ 0, or its t-statistic is below 1.5, the diagnosis warns you explicitly: you cannot meaningfully detect the decay of an edge that never showed up.
2. Simultaneous drawdown bands
Monitoring is continuous, so pointwise percentile thresholds would fire far more often than their nominal level (checking a "95%" line every day for a year yields many times 5% false alarms). The corridor uses simultaneous bands instead:
q(t)= the mean drawdown curve under H0 at each operating dayt(drawdown in $ from the running peak of the additive equity, starting flat at the window start);- each H0 path gets a sup-statistic
M = max_t DD(t) / q(t); - the band at level α is
c · q(t)withcthe(1 − α)quantile ofM— so the probability that a healthy path crosses the band anywhere on the horizon is α, by construction.
Three levels are drawn: Watch (α = 4×stop budget), Reduce (2×) and Stop (the α you set,
default 5%). This 4×/2×/1× spacing is the default anchored ladder, not a theorem — Stop is the
most consequential action so it gets the tightest (rarest) false-alarm budget, Watch the loosest
because it never touches capital. You can switch any level off or give each its own α (see
Customising the governance). Thresholds are calibrated over an
evaluation horizon of max(window, 252) operating days, so the α budget reads as "false alarms per
operating year"; a shorter live window observes only the first part of the boundary and is therefore
conservative.
3. CUSUM detector
The bands watch the path; Page's CUSUM watches the mean. In σ-units of the baseline:
S(t) = max(0, S(t−1) + (k − x(t)) / σ), k = μ_deflated / 2
k is the classic reference value for detecting a drift from the deflated healthy mean toward zero.
The statistic charges while the strategy runs below its deflated edge and discharges when it earns.
Alarm thresholds are the bootstrap quantiles of max S under H0 at the same α budgets.
For the two levels that touch capital (Reduce, Stop) the α budget is split Bonferroni-style between the DD band and the CUSUM (each calibrated at α/2), so the joint false-alarm rate stays at or below the budget — and the empirically measured joint rate is reported, not assumed.
4. Monitor-only signals
Two additional signals can raise the Watch state only (they never touch capital, so they are kept loose): a rolling profit factor below the sup-corrected healthy band (the α-quantile of per-path minima under H0), and time under water beyond the 90th percentile of H0 maxima.
5. Governance state machine
| State | Risk applied | Enter when |
|---|---|---|
| Operating | 100% | default |
| Watch | 100% | DD > watch band, CUSUM in watch zone, PF low or TUW high |
| Reduced | reduce factor (default 50%) | DD > reduce band or CUSUM ≥ reduce threshold |
| Stopped | 0% | DD > stop band or CUSUM ≥ stop threshold |
| Phased re-entry | reduce factor | after cooldown, with signals settled |
Discipline rules, all in operating days: escalation is immediate; de-escalation steps down one
level only after 5 consecutive quieter days (hysteresis); a stop starts a cooldown of
max(10, block length) days; re-entry requires the shadow drawdown back under the watch band and
the CUSUM discharged below 25% of its stop threshold; a failed re-entry (severity rising again)
re-stops immediately; at most one restart per 40 days (anti flip-flop lockout).
No lookahead: the risk factor applied to day t is decided by the state at the end of day t − 1. Health is always evaluated on the pure (shadow) P/L, never on the overlay-reduced one.
Customising the governance
The three levels are not fixed. What is mathematically load-bearing stays fixed; what is a design convention is yours to change.
Fixed (there is a reason). The Bonferroni ½-split between the drawdown band and the CUSUM on the
capital-touching levels (so the joint false-alarm rate stays within budget); the CUSUM reference
value k = μ_deflated / 2 (Page-optimal for a drift toward zero); and calibrating every threshold as
a bootstrap sup-quantile of a false-alarm budget. Watch/Reduce/Stop are the same three levels seen
by two detectors (the band and the CUSUM), so they always move together.
Yours to change (it is a convention). Whether a level exists at all, and the α spacing between them.
- Switch levels on or off. Each level (its band and its CUSUM threshold) can be disabled — a
disabled level simply never fires. Presets set the switches for you:
- Graduated — Watch → Reduce → Stop (the default full ladder).
- Kill-switch — Watch then Stop, no Reduce. Risk becomes binary (100% or 0%), and the phased re-entry after a stop is binary too (straight back to 100%, no partial step). This is the mode for a single-contract strategy, where you physically cannot hold "half" a position.
- Reduce-only — Watch → Reduce, no Stop: the overlay throttles risk but never goes flat.
- Custom — any combination (at least one level must stay on).
- Reduce factor. The size kept in the Reduced state (default 50% = halve; 25% = cut by three quarters). It is also the risk of the phased re-entry — except in a Reduce-off mode, where re-entry is binary.
- Per-level α (extended mode). By default the three budgets follow the anchored 4×/2×/1× ladder
off the Stop budget. Turn on Extended threshold control in Settings → General → Equity
Control to give each level its own independent α (e.g. Watch 15%, Reduce 6%, Stop 3%). The budgets
must stay monotonic —
α Stop ≤ α Reduce ≤ α Watchacross the enabled levels — otherwise the bands would cross and the diagnosis is rejected with a clear message.
This changes governance, not the health verdict
Turning levels off changes what the overlay does and its cost/benefit simulation, not the underlying health reading: P(edge intact), the path anomaly and the CUSUM/drawdown statistics are computed the same way regardless of which levels are armed. With Stop off there is no "wrongful stop" to count, so detection under the breakage scenarios is measured on the first throttle instead.
The verdict numbers
- P(edge intact) — a Bayesian posterior probability that the monitoring window's mean P/L is still positive: prior centred on the deflated baseline edge with weight equivalent to 20 operating days, likelihood from the observed window, pooled baseline σ. A probability, not a p-value.
- Path anomaly — the percentile of the live path against a fresh, independent batch of H0 scenarios (never the calibration batch), taken jointly over the DD sup-statistic, the CUSUM max and the rolling-PF minimum on the same horizon. 90% = more anomalous than 9 of 10 healthy scenarios; below ~80% is physiology.
Overlay feasibility, before anything else
An on/off overlay adds expected value only if the P/L is serially dependent — if losing periods cluster, so the recent past predicts the near future. On serially independent P/L with a positive edge, any drawdown rule has negative expected value: every skipped day skips a positive-mean day. It can still be rational as insurance (paying return to shorten the tail), but that is a different purchase and the module says so.
Four tests run on the full history: Ljung-Box on P/L (memory in returns), runs test on signs
(clustering of wins/losses), loss persistence P(loss | loss) − P(loss) with a permutation
p-value, and Ljung-Box on |P/L| (volatility clustering: predictable risk, not direction). Two or
more significant mean-tests → dependence present; one, or volatility clustering only → weak;
none → absent, and the verdict tells you to read the healthy-scenario cost as an insurance premium.
The honest evaluation
Thresholds are calibrated on one batch of H0 paths; all costs and benefits are measured on independent batches (a light double bootstrap), so the overlay never gets to grade its own homework:
- Healthy scenario (H0) — the overlay applied to fresh healthy paths: probability of a wrongful stop within the horizon, wrongful stops per year, median/mean cost in $, probability the overlay ends worse, mean time flat. This is the price of the insurance.
- Dead edge (H1) — mean shifted to zero. Detection here is structurally slow (the signal is the absence of profits, not the presence of losses); the module reports the honest detection rate and lag instead of hiding them.
- Inverted edge (H1) — mean shifted to
−μ_deflated: outright breakage. Detection rate, median lag, median capital saved, median max-DD reduction — this is where the overlay earns its keep. - Replay — the overlay re-run on the actually observed window (descriptive, single path): time reduced/flat, stops and re-entries, losses avoided vs gains missed, and their ratio (protection efficiency). These facts appear as an interventions strip inside the comparison panel (final P/L and max drawdown with/without overlay are the corresponding table rows). This path is also played back interactively (below).
The healthy/dead/inverted ledgers sit behind a Counterfactual stress tests disclosure, collapsed by default — open it when you want the full cost/benefit accounting.
Interactive replay
The replay is a scrubbable timeline, not a static chart. It opens on the finished window — both equity lines fully drawn, the slider parked at the far right. Drag the slider back toward the left to retrace the path day by day, or press Play to rebuild it forward from the start. The always-on and with-overlay equity curves grow together and visibly diverge wherever the overlay throttles risk (shaded spans). Each governance transition — Watch, Reduce, Stop, gradual re-entry — appears on the exact day it fires, marked on the axis, and listed in the transition log beneath the player with its cause and the numbers (e.g. "Reduced — CUSUM 5.24 ≥ 5.00", or "DD beyond the Reduce band"). The log is synced with the playhead — the current event is highlighted, entries past the cursor are dimmed — and clicking a row jumps the replay to that instant. Directly below the equity chart, the CUSUM detector shares the same playhead, so you watch the statistic load toward a threshold, cross it, trigger the intervention, then discharge and re-arm. A live readout follows the cursor: current date, state, applied risk, the overlay's running effect (Δ), and the CUSUM value.
Always-on vs With Equity Control
A side-by-side metrics table compares the two versions, with the better value of each row highlighted. The numbers come from the same engine as the Metrics page — net PnL, return, CAGR, max drawdown ($ and %), MAR (= CAGR / max drawdown), Sharpe, Sortino, annual volatility, win rate, profit factor — with the delta per row. A toggle switches the scope:
- Monitored window — the live window only, where the overlay acts. Isolates the EC effect.
- Whole account — the full track (In-Sample + live). The In-Sample is identical for both versions (the overlay never touches the calibration), so the difference is the tail — but on a profitable full track the risk-adjusted ratios become interpretable again.
The highlight marks the better value only where the direction is unambiguous; for the risk-adjusted ratios it is suppressed on a losing window (see below), and volatility is never flagged (lower is not inherently better). Below the table, the interventions strip lists the replay facts — stops, re-entries, time reduced/flat, losses avoided, gains missed, protection efficiency — always referred to the monitored window regardless of the scope toggle.
Ratios on a losing window
When the window is in loss, the risk-adjusted ratios (MAR, Sharpe, Sortino) invert and become misleading: dividing a negative return by a much smaller volatility makes the ratio look worse for the version that actually lost less. In that regime read PnL, drawdown and volatility — which are unambiguous — and treat the ratios as meaningful only when the return is positive. The table shows a caveat automatically whenever either version's return is negative.
How to decide
Read three numbers together: the feasibility verdict, the healthy-scenario cost, and the inverted-edge savings. If dependence is absent and the healthy cost is material, the overlay is expensive insurance for your strategy — knowing that is exactly the point of the module.
Parameters
| Parameter | Default | Range | Meaning |
|---|---|---|---|
| In-Sample end | — (required) | any session date | date where the In-Sample ends; the rest is the live window (takes precedence over Live tail) |
| Live tail | — (optional) | 10 – 2000 | final operating days classified as live; alternative to In-Sample end (under Advanced) |
| Monitor from / To | full history | any session date | calendar bounds of the analysed window (To = as-of date) |
| Edge haircut | 25% | 0 – 50% | deflation of the baseline mean under H0 |
| False-alarm budget α (Stop) | 5% | 1 – 20% | wrongful-stop budget per ~operating year; anchors the default ladder (Reduce 2α, Watch 4α) |
| Governance preset | Graduated | Graduated · Kill-switch · Reduce-only · Custom | which levels are armed (see Customising the governance) |
| Levels on/off | all on | per level | disable Watch, Reduce or Stop individually; at least one must stay on |
| Reduce factor | 50% | 10 – 90% | size kept in the Reduced state (50% = halve, 25% = cut by three quarters); also the phased re-entry risk |
| Per-level α | anchored ladder | 1 – 50% each | independent α per level; requires Extended threshold control in Settings; must stay monotonic (Stop ≤ Reduce ≤ Watch) |
| Bootstrap paths | 2000 | 500 – 20000 | calibration batch (evaluation batches are half, min 500) |
| Block length | auto (Politis-White) | 2 – 500 | stationary-bootstrap expected block |
| Rolling PF window | 20 | 10 – 60 | operating days of the monitor-only PF signal (Watch level only) |
Assumptions and limits
- Equity is additive in dollars (fixed position size), consistent with the rest of VECTOR's default model; drawdowns and bands are in $ from the running peak of the monitoring window.
- The bootstrap can only recombine what the baseline contains: a regime that never appears in the baseline cannot be simulated. Thresholds are as good as the baseline is representative.
- Everything is computed batch-style on the data you uploaded: refresh the CSV and re-run to update the diagnosis. There is no live feed, and no order is ever sent.
The diagnosis runs as a background job like the other simulations: the POST returns a job_id,
the client polls, and the run survives tab switches, phone lock and even a backend restart
(see API reference).